前端常见的设计模式

前端开发中经常用到比如单例模式(全局工具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 消息推送 服务端推送,前端多个模块订阅不同消息 ✅ 是
相关推荐
IMPYLH2 小时前
HTML 的 <wbr> 元素
前端·html
Dovis(誓平步青云)3 小时前
常用命令藏得太深?怎么做一个快捷命令坞
运维·前端·自动化·音视频·prometheus
IT_陈寒3 小时前
Vite的这个问题坑了我三天,原来如此解决!
前端·人工智能·后端
网易云信3 小时前
大模型能上岗做销售吗?我们让 12 款国产模型交了 420 份作业
前端·后端
蜗牛互联网4 小时前
Python Agent工具调用的白名单、参数校验与审批门禁
java·服务器·前端·人工智能·后端·python
计算机魔术师4 小时前
Perplexity:每个 Project 都是一个 Git 仓库
前端
Andrew5514 小时前
让 AI 写页面不再“一眼假”:我把设计品味做成了一个 Claude Code Skill 流水线
前端
乐享qicheng4 小时前
14-AI智能管家JSBridge深度问答
前端
10年前端老司机4 小时前
我用 Vue3 + LangGraph 做了个心理咨询 AI,踩了 9 个坑后总结出来的实战经验
前端·langchain·agent
数据掘金4 小时前
A/B 实验分组参数回滚后还在生效?一次参数校验体系的重构复盘
前端