当前位置: 首页 > article >正文

高级前端工程师必备的 JS 设计模式入门教程,常用设计模式案例分享

目录

高级前端工程师必备的 JS 设计模式入门教程,常用设计模式案例分享

一、什么是设计模式?为什么前端也要学?

1、设计模式是什么

2、设计模式的产出

二、设计模式在 JS 里的分类

三、常用设计模式实战讲解

1、单例模式(Singleton)

2、工厂模式(Factory)

3、观察者模式(Observer)

4、代理模式(Proxy)

5、策略模式(Strategy)

6、建造者模式、适配器模式、装饰器模式和状态模式

①建造者模式(Builder Pattern)

②适配器模式(Adapter Pattern)

③装饰器模式(Decorator Pattern)

④状态模式(State Pattern)

四、结语


        作者:watermelo37

        CSDN万粉博主、华为云云享专家、阿里云专家博主、腾讯云、支付宝合作作者,全平台博客昵称watermelo37。

        一个假装是giser的coder,做不只专注于业务逻辑的前端工程师,Java、Docker、Python、LLM均有涉猎。

---------------------------------------------------------------------

温柔地对待温柔的人,包容的三观就是最大的温柔。

---------------------------------------------------------------------

高级前端工程师必备的 JS 设计模式入门教程,常用设计模式案例分享

本文适合有JavaScript基础 、 Vue/React 开发经验,但对设计模式不太熟悉的前端开发工程师。

        什么是设计模式?为什么要有设计模式?单例模式、工厂模式、建造者模式、适配器模式、代理模式、装饰器模式、观察者模式、策略模式、状态模式分别是什么?他们解决了什么样的问题?本文将给您答案。

一、什么是设计模式?为什么前端也要学?

1、设计模式是什么

        设计模式,就是程序员们总结出来的一套解决常见代码问题的方法论

  • 它不是死板的规定,不是必须按部就班执行。

  • 它是经验总结,告诉你在遇到某些类型的问题时,如何写出更优雅、更健壮、更可扩展的代码。

  • 后端用,前端也用,尤其是当你的项目越来越大、多人协作越来越复杂时,设计模式就越重要。

        类比一下:设计模式就像打游戏时的「固定套路」,让你在遇到不同怪物时不用每次重头想招数,而是有一套拿得出手的打法。

2、设计模式的产出

        设计模式的产出不是特定代码片段,而是一套可复用的设计思路或结构

  • 有些模式产出一个「结构」(比如单例产出一个唯一对象)。

  • 有些模式产出一个「流程/机制」(比如观察者产出的是发布-订阅机制)。

  • 也有些是组合型的,既有对象也有通信逻辑。

        设计模式产出的是「结构 + 行为」的组合,没有严格固定形式,但背后有固定的“意图”或“问题场景”。我们关注的就是其“意图”和“场景”。

二、设计模式在 JS 里的分类

        设计模式很多,但最重要的,可以分成三大类:

类型解释代表模式
创建型解决「如何创建对象」的问题单例模式、工厂模式、建造者模式
结构型解决「对象之间怎么组织结构」的问题适配器模式、代理模式、装饰器模式
行为型解决「对象之间怎么协作通信」的问题观察者模式、策略模式、状态模式

三、常用设计模式实战讲解

1、单例模式(Singleton)

        定义:整个系统只存在一个实例对象,并且能全局访问。

        举个例子,Vuex里面的store就是单例,事件总线(Event Bus)也是单例。

        来做个简单的实现,它通过一个静态属性 instance 储存实例,并在重复创建时返回已有实例,这样就能实现单例的效果:

class Store {constructor() {if (Store.instance) {return Store.instance;}this.state = {};Store.instance = this;}
}const a = new Store();
const b = new Store();console.log(a === b); // true

2、工厂模式(Factory)

        定义:用一个函数/类专门负责创建对象,不直接用 new。

        举几个例子,组件封装:根据类型不同返回不同组件实例还有 Axios 的实例化都是工厂模式。

        工厂模式的优势在于能统一创建逻辑,并且拓展非常方便,各类型之间高内聚,低耦合。做个简单的实现:

function createButton(type) {if (type === 'primary') {return { color: 'blue', size: 'large' };} else if (type === 'danger') {return { color: 'red', size: 'large' };}
}const btn = createButton('primary');
console.log(btn); // { color: 'blue', size: 'large' }

工厂函数是什么? 

        工厂函数(Factory Function)是一个普通函数,它封装了创建对象的过程,并返回这个对象。它是实现工厂模式的一种方式,但不限于工厂模式使用。

function createPerson(name, age) {return {name,age,sayHello() {console.log(`Hi, I'm ${name}`);}}
}const person = createPerson('Tom', 20);

        这个案例中的 createPerson 就是工厂函数。

3、观察者模式(Observer)

        定义:一对多关系,一个对象变化,通知所有依赖它的对象。

        比如Vue 响应式,发布订阅(EventEmitter)都属于观察者模式。

        一般情况下,观察者模式里面一定有一个叫做 notify / emit / publish 或类似功能的函数,用来通知所有的订阅者,这种函数本质上就是广播机制,是观察者模式的核心实现函数。做个简单的案例:维护一组回调,变化时循环触发。

class Observer {constructor() {this.subscribers = [];}subscribe(fn) {this.subscribers.push(fn);}notify(data) {this.subscribers.forEach(fn => fn(data));}
}const obs = new Observer();obs.subscribe((data) => console.log('收到1', data));
obs.subscribe((data) => console.log('收到2', data));obs.notify('你好');
// 收到1 你好
// 收到2 你好

4、代理模式(Proxy)

        定义:通过一个代理对象控制对目标对象的访问。

        Vue3的响应式Proxy、接口请求封装都属于代理模式。

        先用Proxy举例:

const target = {name: '张三'
};const proxy = new Proxy(target, {get(obj, prop) {console.log(`访问属性:${prop}`);return obj[prop];},set(obj, prop, value) {console.log(`设置属性:${prop}=${value}`);obj[prop] = value;return true;}
});proxy.name; // 访问属性:name
proxy.age = 20; // 设置属性:age=20

        这个例子比较常见,是不是意犹未尽?我们再来一个图片懒加载的代理模式来举例:

// 真正加载图片的方法
function loadImage(src) {const img = new Image();img.src = src;document.body.appendChild(img);
}// 创建一个代理来控制图片加载
const proxyImage = (function () {let img = new Image();img.onload = function() {loadImage(this.src); // 真正加载}return function(src) {// 先用一张 loading 图片占位loadImage('loading.jpg');// 真正的图片异步加载完成后替换img.src = src;}
})();// 使用
proxyImage('real-image.jpg');

        proxyImage 函数就是代理对象,loadImage是被代理的目标对象,用户一调用它就显示 loading 图,真正图片在加载完毕后替换。

        这里使用 IIFE(立即执行函数表达式) 是为了创建一次性的私有作用域和闭包,隔离 img 变量,避免污染。

        执行逻辑为:

  1. 代码刚执行时,生成了一个 proxyImage 函数,这个函数内部封装了一个私有的 Image 对象 img,并且给 img.onload 绑定了回调函数。

  2. 调用 proxyImage(src) 时,先 loadImage('loading.jpg') 显示一个占位图,再设置 img.src = src(真实图片地址)。

  3. 这时浏览器会开始异步加载 src 指向的真实图片,这一步是静默执行的,DOM渲染的是默认图片。

  4. 加载完毕后自动触发 img.onload,在回调里重新调用 loadImage(this.src),替换成真实图。

        其中,默认图片(loading.jpg)应该是一个极小的图,通过base64编码内嵌到代码里,或者直接用svg小图标,如果是个大一点的图片应该让浏览器预加载,以此来实现用户视角下的默认图片无感渲染。

5、策略模式(Strategy)

        定义:将一系列算法封装成独立的策略类,使它们可以互相替换。

        比如一些表单验证、支付方式切换过程等。

        其优势在于具有开闭原则(增加新策略不用改老代码),并且代码可扩展。举例如下,其中strategies 里是具体的策略集合(算法实现),validate 是「上下文」调用器(根据情况选择策略执行),两者配合才构成完整的策略模式实现:

const strategies = {isNonEmpty(value) {return value !== '';},minLength(value, length) {return value.length >= length;}
};function validate(value, rule, ...args) {return strategies[rule](value, ...args);
}console.log(validate('abc', 'minLength', 2)); // true

开闭原则:

        即对扩展开放,对修改关闭。

        产生新需求时,应该通过新增代码来实现,而不是修改现有代码。这样可以减少出错的风险,提高系统的稳定性。

        在策略模式中,策略模式增加新策略,只是添加新策略对象,不需要去改 validate 函数本体

        有没有觉得策略模式和工厂模式很像?都是通过一个“judge info”(type与rule)来判断到底该如何执行。但他们存在以下区别:

策略模式工厂模式
关注执行逻辑不同关注对象创建不同
替换算法/规则替换对象
运行时切换生成时选择

6、建造者模式、适配器模式、装饰器模式和状态模式

        这四个相对少见,简单介绍:

①建造者模式(Builder Pattern)

        分步骤构建一个复杂对象,而不是一口气构造。比如建一台电脑:

class ComputerBuilder {constructor() {this.computer = {};}addCPU(cpu) {this.computer.cpu = cpu;return this;}addRAM(ram) {this.computer.ram = ram;return this;}addStorage(storage) {this.computer.storage = storage;return this;}build() {return this.computer;}
}const myComputer = new ComputerBuilder().addCPU('Intel i9').addRAM('32GB').addStorage('1TB SSD').build();
②适配器模式(Adapter Pattern)

        让原本接口不兼容的两个类可以一起工作。比如一个老版 API 返回的是 snake_case,但新系统要求 camelCase:

function oldApi() {return { user_name: 'Tom', user_age: 20 };
}// 适配器
function adapterApi() {const data = oldApi();return {userName: data.user_name,userAge: data.user_age};
}const result = adapterApi();
③装饰器模式(Decorator Pattern)

        在不修改原对象的情况下,动态增加功能。比如增强 log 函数(这里相当于额外打印了时间):

function log(msg) {console.log(msg);
}// 装饰器
function withTimestamp(fn) {return function(...args) {console.log(`[${new Date().toISOString()}]`);return fn(...args);}
}const decoratedLog = withTimestamp(log);
decoratedLog('Hello World');
④状态模式(State Pattern)

        对象内部状态不同,行为也不同。比如电灯开关:

class Light {constructor() {this.state = 'off';}toggle() {if (this.state === 'off') {console.log('Turning on');this.state = 'on';} else {console.log('Turning off');this.state = 'off';}}
}const light = new Light();
light.toggle(); // Turning on
light.toggle(); // Turning off

四、结语

        设计模式能让人写出更稳定、可维护的代码,JavaScript中最常用的设计模式有单例、工厂、观察者、代理、策略五种。学设计模式就相当于学解决复杂问题的套路,在框架中,如 Vue / React项目里,几乎随处可见设计模式的身影。

        只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~

        其他热门文章,请关注:

        极致的灵活度满足工程美学:用Vue Flow绘制一个完美流程图

        你真的会使用Vue3的onMounted钩子函数吗?Vue3中onMounted的用法详解

        DeepSeek:全栈开发者视角下的AI革命者

        通过array.filter()实现数组的数据筛选、数据清洗和链式调用

        通过Array.sort() 实现多字段排序、排序稳定性、随机排序洗牌算法、优化排序性能

        TreeSize:免费的磁盘清理与管理神器,解决C盘爆满的燃眉之急

        通过MongoDB Atlas 实现语义搜索与 RAG——迈向AI的搜索机制

        深入理解 JavaScript 中的 Array.find() 方法:原理、性能优势与实用案例详解

        el-table实现动态数据的实时排序,一篇文章讲清楚elementui的表格排序功能

        MutationObserver详解+案例——深入理解 JavaScript 中的 MutationObserver

        JavaScript中通过array.map()实现数据转换、创建派生数组、异步数据流处理、DOM操作等

        前端实战:基于Vue3与免费满血版DeepSeek实现无限滚动+懒加载+瀑布流模块及优化策略

        高效工作流:用Mermaid绘制你的专属流程图;如何在Vue3中导入mermaid绘制流程图

        干货含源码!如何用Java后端操作Docker(命令行篇)

        在线编程实现!如何在Java后端通过DockerClient操作Docker生成python环境

        Dockerfile全面指南:从基础到进阶,掌握容器化构建的核心工具

相关文章:

高级前端工程师必备的 JS 设计模式入门教程,常用设计模式案例分享

目录 高级前端工程师必备的 JS 设计模式入门教程,常用设计模式案例分享 一、什么是设计模式?为什么前端也要学? 1、设计模式是什么 2、设计模式的产出 二、设计模式在 JS 里的分类 三、常用设计模式实战讲解 1、单例模式(S…...

unix/linux source 命令,其发展历程详细时间线、由来、历史背景

追本溯源,探究技术的历史背景和发展脉络,能够帮助我们更深刻地理解其设计哲学和存在的意义。source 命令(或者说它的前身和等效形式)的历史,与 Unix Shell 本身的发展紧密相连。 让我们一起踏上这段追溯之旅,探索 source 命令的由来和发展历程。 早期 Unix Shell 与命令…...

2023年电赛C题——电感电容测量装置

一、赛题 二、题目分析——损耗角正切值 对于一个正常的正弦波信号,如果通过的是一个电阻或一条导线,那么它的电流信号和电压信号是一致的(有电压才有电流),没有相位差。 但是如果正弦波经过了一个电感或电容&#xf…...

pycharm打印时不换行,方便对比观察

原来: 优化: import torch torch.set_printoptions(linewidth200) 优化结果:...

因泰立科技:镭眸T51激光雷达,打造智能门控新生态

在高端门控行业,安全与效率是永恒的追求。如今,随着科技的飞速发展,激光雷达与TOF相机技术的融合,为门控系统带来了前所未有的智能感知能力,开启了精准守护的新时代。因泰立科技的镭眸T51激光雷达,作为这一…...

Microsoft Fabric - 尝试一下Data Factory一些新的特性(2025年5月)

1.简单介绍 Microsoft Fabric是微软提供的一个数据管理和分析的统一平台,感觉最近的新特性也挺多的。 Data Factory是Microsoft Fabric的一个功能模块,也是一个cloud service。Data Factory可以和多种数据源进行连接,同时提供了data movemen…...

NodeJS全栈开发面试题讲解——P10微服务架构(Node.js + 多服务协作)

✅ 10.1 单体架构和微服务的主要区别是什么? 维度单体架构微服务架构模块组织所有功能打包在一个代码仓库中拆分为多个独立服务部署方式部署一次包含全部逻辑各服务独立部署、独立扩缩容开发协作多人协作易冲突团队按服务划分,职责清晰可维护性功能多时…...

【前端】javascript和Vue面试八股

面试暂时没有遇到过考这么深的,一般还是问一些生命周期和性能相关。 Q:什么情况下“ a 1 && a 2 && a 3 ”同时成立 A:对象的valueOf与toString方法:当一个对象与一个原始值(如数字)进…...

WEB3——区块链留言板(留言上链),查看web3日志-入门项目推荐

区块链留言板(留言上链) 目标:构建一个用户可以“写入留言、读取历史留言”的 DApp。 内容: Solidity 编写留言合约,存储留言内容和发送者地址。 提供 API: GET /messages:获取留言列表 POST…...

开源库免费API服务平台 ALLBEAPI

开源库API化平台 ALLBEAPI 🌊 GitHub仓库地址:https://github.com/TingjiaInFuture/allbeapi 为优秀开源库提供免费 API 服务,让开发者无需安装和部署即可直接调用。 🌐 API 接入地址 基础 URL: https://res.allbeapi.top 所…...

【配置vscode默认终端为git bash】

配置vscode默认终端为git bash 点击左下角小齿轮,点击设置,搜索terminal.integrated.profiles.windows,点击在setting.json中编辑 第一部分是当前的所有的终端,第二部分是配置默认的终端"terminal.integrated.defaultProfi…...

Cloudflare

Cloudflare 是一个网络基础设施和网站安全服务提供商,它的主要作用是让网站 更快、更安全、更可靠。简单来说,它是一个“护盾 加速器”。 🧩 Cloudflare 的主要功能: 1. 🚀 加速网站访问(CDN&#xff09…...

Cypress + TypeScript + Vue3

🚀 从零构建 Cypress + TypeScript + Vue3 组件测试环境【详细实战教程】 组件测试是前端开发中不可忽视的一环,它能够帮助我们在开发阶段就发现 UI 与交互逻辑问题。本文将带你手把手搭建基于 Cypress + TypeScript + Vue3 的组件测试环境,包含完整目录结构、配置文件、组…...

Oracle DG库控制文件IO错误导致宕机的应急处理

Oracle DG库控制文件IO错误导致宕机的应急处理 事故现场偷天换日棋差一招事故现场 一套Oracle 19c DG环境的备库宕机。 根据告警时间检查实例宕机时间点附近的alert日志有如下重要信息: 2025-05-25T23:34:10.705385+08:00 KCF: read, write or open error, block=0x3377ee …...

​​技术深度解析:《鸿蒙5.0+:全场景能效的产业革命》​

​​引言:万物智联时代的功耗新范式​​ ​​产业痛点​​: 全球IoT设备年耗电量突破200TWh,传统系统架构难以支撑千亿级终端低功耗需求。​​鸿蒙5.0战略定位​​: 通过​​全场景能效架构​​(端侧极致优化跨端智能…...

Spring Boot启动慢?Redis缓存击穿?Kafka消费堆积?——Java后端常见问题排查实战

Spring Boot启动慢?Redis缓存击穿?Kafka消费堆积?——Java后端常见问题排查实战 引言 Java后端系统因其丰富的技术栈和复杂的业务逻辑,常常面临启动延迟、性能瓶颈、异常错误等多种挑战。从核心语言、Web框架到分布式微服务及缓…...

深入解析 IP 代理:原理、应用场景与优化策略

在当今数字化时代,网络通信的安全性与隐私保护成为人们日益关注的焦点,而 IP 代理作为网络技术领域的一个重要概念,正扮演着愈发关键的角色。本文将深入剖析 IP 代理的原理、广泛的应用场景以及如何对其进行优化,以期为读者提供有…...

58、辣椒种植学习

辣椒(学名:Capsicum annuum)属于茄科辣椒属,是一种重要的蔬菜兼调味作物,具有较高的经济价值和营养价值。其果实富含维生素C、辣椒素等成分,既可鲜食,也可加工成干辣椒、辣椒粉、辣椒酱等产品&a…...

【SpringBoot】零基础全面解析SpringBoot配置文件

本篇博客给大家带来的是SpringBoot配置文件的知识点, 有properties 配置文件 和 yml 配置文件, 目前主流的是yml,所以本文以 重点讲解 yml 配置文件. 🐎文章专栏: JavaEE进阶 👉gitte链接: 薯条不要番茄酱 🚀若有问题 评论区见 ❤ 欢迎大家点…...

python:PyMOL 能处理 *.pdb 文件吗?

PyMOL 完全可以打开并处理 PDB(Protein Data Bank)文件,这是 PyMOL 最主要的功能之一。PDB 格式是结构生物学领域的标准文件格式,专门用于存储生物大分子(如蛋白质、核酸)的三维结构数据。 在 PyMOL 中打开…...

GNSS终端授时之四:高精度的PTP授时

我们在GNSS终端的授时之三:NTP网络授时中介绍了NTP网络授时的基本原理。我们知道了NTP授时的精度跟网络环境相关,即使在局域网中NTP授时的精度也只能到ms级别。如果广域网,经过多级交换机,路由器,由于传输路径和延时的…...

Vim文本编辑器快捷键用法以及简单介绍

目录 vim文本编辑器 简介: 语法: vim模式介绍: 模式切换: 用法: 编辑模式: 一般模式: 命令模式: vim文本编辑器 简介: 在命令行界面下,最常用的文本…...

CppCon 2014 学习:C++ in Huge AAA Games

“Nicolas Fleury, Technical Architect” 这份主题为 “C in Huge AAA Games” 的内容理解,可以从几个方面切入: 1. 背景 AAA大作游戏(Triple-A Games)指的是预算高、规模大、制作精良的顶级游戏项目。这些游戏通常代码库庞大&…...

PHP与MYSQL结合中中的一些常用函数,HTTP协议定义,PHP进行文件编程,会话技术

MYSQL: 查询函数: 执行查询语句: 1.mysql_query("SQL语法"); 凡是执行操作希望拿到数据库返回的数据进行展示的(结果返回: 数据结果); 2.执行结果的处理:成功为结果集,失败为false; 成功返回结果:SQL指令没有错误,但是查询结果…...

MapReduce 分布式计算模型

练习题 单词计数 需求&#xff1a;统计每个单词数量 "Hello World Hello Hadoop Hello MapReduce" 实现&#xff1a; map阶段&#xff1a;拆分成单词&#xff0c;执行map函数输出键值对<word, 1> <Hello, 1> <World, 1> <Hello, 1> <…...

Vue3 + Element Plus 防止按钮重复点击的解决方案

在 Vue3 和 Element Plus 项目中&#xff0c;防止按钮重复点击是一个常见的需求&#xff0c;特别是在表单提交、支付等场景下。以下是几种实现方式&#xff1a; 1. 使用 Element Plus 的 loading 状态 Element Plus 的按钮组件本身就支持 loading 状态&#xff0c;这是最简单…...

测试工程师学LangChain之promptTemplate 实战笔记

一、引言:大模型时代的测试自动化革命 2025 年,随着大模型(如 DeepSeek)在自动化测试领域的广泛应用,Prompt 编写已成为测试工程师的核心技能之一。 为什么? 大模型输出的质量 90% 取决于输入的 PromptLangChain 的 PromptTemplate 提供了参数化 Prompt 的标准化方案Ope…...

OpenCV计算机视觉实战(9)——阈值化技术详解

OpenCV计算机视觉实战&#xff08;9&#xff09;——阈值化技术详解 0. 前言1. 全局阈值与自适应阈值2. Otsu 算法3. 实战案例&#xff1a;文档扫描中的二值化处理4. 算法对比小结系列链接 0. 前言 在图像处理领域&#xff0c;阈值化 (Binarization) 技术就像一把魔术剪刀&…...

【Tauri2】049——upload

前言 这篇就看看一个简单地插件——upload Upload | Taurihttps://tauri.app/plugin/upload/upload的英文意思是“上传&#xff08;程序或信息&#xff09;”。 看来是用来上传文件的。 支持移动端 正文 安装 pnpm tauri add upload 在前后端都会安装&#xff0c;即 .plug…...

4、数据标注的武林秘籍:Label-Studio vs CVAT vs Roboflow

开篇痛点&#xff1a;90%的模型效果取决于数据质量 "标注3小时&#xff0c;训练5分钟"——这是很多AI工程师的真实写照。上周有位读者训练YOLOv12时发现&#xff0c;同样的代码&#xff0c;换批数据mAP直接跌了15%&#xff0c;根本原因是标注不规范&#xff01;本文…...