前端开发中经常用到比如单例模式(全局工具redux)、观察者模式(状态管理 / 事件)、策略模式(表单验证)、代理模式(响应式 / 懒加载)、装饰器模式(高姐组件)、组合模式(UI 嵌套结构)等。
| 设计模式 | 类别 | 前端中的应用例子 |
|---|---|---|
| 单例模式 | 创建型 | 全局 HTTP 客户端、Logger、Store |
| 工厂模式 | 创建型 | 创建不同类型的组件 / 消息 / 模块 |
| 观察者模式 | 行为型 | 事件系统、状态管理、Pub/Sub、React 响应式 |
| 策略模式 | 行为型 | 表单验证、支付方式、排序策略 |
| 代理模式 | 结构型 | Vue 3 响应式、图片懒加载、接口代理 |
| 装饰器模式 | 结构型 | React 高阶组件(HOC)、功能增强 |
| 组合模式 | 结构型 | 组件树、菜单、文件目录、嵌套 UI |
| 适配器模式 | 结构型 | 适配不同接口、数据格式转换 |
| 模板方法 | 行为型 | 组件生命周期、基类复用逻辑 |
| 命令模式 | 行为型 | 操作队列、撤销重做、按钮行为封装 |
✅ 1. 单例模式
保证一个类只有一个实例,并提供全局访问点。
🧩 前端场景:
实现:
javascript
✅ 方式 1:使用模块化导出单例(推荐,ES Module / CommonJS)
在 JS 模块系统中,模块默认就是单例的! 因为模块在首次加载后会被缓存,再次 import 时拿到的始终是同一个实例。
🧩 例子:一个全局的 Logger(日志工具)
// logger.js
class Logger {
log(message) {
console.log(`[LOG]: ${message}`);
}
}
// 导出单例实例
const logger = new Logger();
export default logger;
使用:
// a.js
import logger from './logger';
logger.log('来自模块 A');
// b.js
import logger from './logger';
logger.log('来自模块 B');
// 控制台输出:
// [LOG]: 来自模块 A
// [LOG]: 来自模块 B
// 但 logger 是同一个实例!
✅ 2. 工厂模式
提供一个创建对象的接口,但由子类决定实例化哪个类,将对象创建和使用分离。
🧩 前端场景:
-
创建不同类型的组件 / 模块 / 消息提示(比如 SuccessAlert / ErrorAlert)
-
创建不同类型的 UI 组件(表单、按钮、弹窗)
🧩 例子:创建不同类型的弹窗
javascript
function createAlert(type, message) {
switch (type) {
case 'success':
return { type: 'success', message, bgColor: 'green' };
case 'error':
return { type: 'error', message, bgColor: 'red' };
default:
return { type: 'info', message, bgColor: 'blue' };
}
}
const successAlert = createAlert('success', '操作成功');
const errorAlert = createAlert('error', '出错了');
✅ 将对象的创建逻辑封装在工厂函数中,调用方无需关心具体实现
✅ 3. 观察者模式
定义对象间的一对多依赖关系,当一个对象状态改变时,所有依赖它的对象都会收到通知并自动更新。
🧩 前端场景:
-
React 状态提升 / 全局状态管理(如 Redux、MobX、Context)
-
自定义事件系统、消息总线、Pub/Sub
-
组件间通信(比如子组件通知父组件,或者多个组件监听同一状态)
🧩 例子:简易的事件订阅 / 发布系统
javascript
class EventEmitter {
constructor() {
this.events = {};
}
on(event, listener) {
if (!this.events[event]) this.events[event] = [];
this.events[event].push(listener);
}
emit(event, ...args) {
if (this.events[event]) {
this.events[event].forEach(fn => fn(...args));
}
}
}
// 使用
const emitter = new EventEmitter();
emitter.on('message', data => console.log('收到消息:', data));
emitter.emit('message', 'Hello Observer!');
✅ 观察者模式是 React 状态驱动、事件机制、全局状态通信的基石
✅ 4. 策略模式
定义一系列算法,把它们一个个封装起来,并使它们可以互相替换。
🧩 前端场景:
-
表单验证策略(比如邮箱验证、手机号验证、密码强度)
-
支付方式选择(支付宝、微信、信用卡,每种支付逻辑不同)
-
排序 / 过滤策略
🧩 例子:表单验证策略
javascript
const strategies = {
isEmail: (val) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val),
isPhone: (val) => /^1[3-9]\d{9}$/.test(val),
};
function validate(type, value) {
return strategies[type] ? strategies[type](value) : false;
}
console.log(validate('isEmail', 'a@b.com')); // true
✅ 将不同的验证逻辑解耦,方便扩展和维护
✅ 5. 代理模式
为其他对象提供一种代理以控制对这个对象的访问。
🧩 前端场景:
-
Vue 3 的响应式原理(基于 Proxy)
-
权限控制、接口请求代理、数据劫持、懒加载代理
🧩 例子:图片懒加载代理
javascript
function createLazyImage(src) {
let img = new Image();
img.src = src;
return {
show: () => {
document.body.appendChild(img);
}
};
}
const lazyImg = createLazyImage('https://example.com/image.jpg');
// 滚动到可视区域时再调用 lazyImg.show()
✅ 代理可以控制对象的访问方式,实现更灵活的功能增强
✅ 6. 装饰器模式
动态地给对象添加额外的职责,而不改变其结构。
🧩 前端场景:
-
React 高阶组件(HOC)
-
给组件添加额外功能(如权限校验、日志、缓存)
-
函数 / 方法增强
🧩 例子:React 高阶组件(HOC 是装饰器的一种实现)
javascript
function withLogging(WrappedComponent) {
return function EnhancedComponent(props) {
console.log('组件被渲染了', props);
return <WrappedComponent {...props} />;
};
}
// 使用
const Enhanced = withLogging(MyComponent);
✅ 装饰器模式让你可以在不修改原组件代码的情况下增强功能
🆕 现代 JS 也支持原生装饰器语法(实验性),常用于类 / 方法增强
✅ 7. 组合模式
将对象组合成树形结构以表示"部分-整体"的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
🧩 前端场景:
-
组件树、DOM 树
-
菜单组件(有子菜单)、文件目录树、UI 嵌套组件
🧩 例子:菜单组件递归渲染子菜单
javascript
function MenuItem({ item }) {
return (
<li>
{item.label}
{item.children && (
<ul>
{item.children.map((child, idx) => (
<MenuItem key={idx} item={child} />
))}
</ul>
)}
</li>
);
}
✅ 组合模式让你可以用一致的方式处理单个对象和组合对象
8.发布订阅模式
| 对比项 | 观察者模式(Observer) | 发布订阅模式(Pub/Sub) |
|---|---|---|
| 🧩 关系 | 观察者(Observer)直接订阅 被观察者(Subject),两者有直接联系 | 发布者(Publisher)和订阅者(Subscriber)彼此不直接认识,通过中间人(Event Bus)通信 |
| 🧩 耦合度 | 相对较高,观察者要知道被观察者 | 更低耦合,发布者和订阅者完全解耦 |
| 🧩 实现方式 | Subject 维护一个 Observers 列表,直接调用它们的更新方法 | 事件中心维护 topic/事件列表,根据订阅的消息分发 |
| ✅ 举例 | Vue 2 中 $emit/ $on(可以认为是简化版 Pub/Sub 或 Observer) |
自定义事件系统、Redux events、RxJS、Node.js EventEmitter |
✅ 观察者模式是 Pub/Sub 的一种特例或简化形式,Pub/Sub 是更通用、更松耦合的通信模式,因此也被广泛认为是一种重要的设计模式。
应用:
| 场景 | 说明 | 是否使用设计模式思想 |
|---|---|---|
| ✅ 浏览器事件机制(addEventListener / dispatchEvent) | 本质是一个发布订阅系统 | ✅ 是 |
| ✅ Vue 自定义事件(emit/on) | 组件间通信,基于发布订阅思想 | ✅ 是 |
| ✅ Redux / Vuex 的 action / dispatcher 机制 | 虽然不是典型的 Pub/Sub,但有相似的消息驱动思想 | ✅ 类似 |
| ✅ Node.js 的 EventEmitter | 经典的发布订阅实现 | ✅ 是 |
| ✅ RxJS Observables | 响应式编程中的核心,是强大的 Pub/Sub / 数据流工具 | ✅ 是 |
| ✅ 前端全局事件总线(EventBus) | 自己封装的事件通信机制,用于非父子组件通信 | ✅ 是 |
| ✅ MQTT / WebSocket 消息推送 | 服务端推送,前端多个模块订阅不同消息 | ✅ 是 |
