web 前端常用的设计模式

模块模式

  • 核心:封装私有变量和方法,仅暴露公共接口。
  • 实现:利用闭包(IIFE)或 ES6 模块化。
  • 场景:
    • 封装工具库(如 utils.js)。
    • 避免全局命名污染。
// ES6 模块
export const publicMethod = () => {
  const privateVar = "私有数据";
  return privateVar;
};

单例模式 (Singleton Pattern)

  • 核心:确保类只有一个实例,全局共享。
  • 场景:
    • 全局状态管理(如 Redux Store、Vuex Store)。
    • 浏览器环境中的全局对象(如 window)。
class Singleton {
  constructor() {
    if (!Singleton.instance) {
      Singleton.instance = this;
    }
    return Singleton.instance;
  }
}
const instance = new Singleton();

发布-订阅模式 (Pub-Sub Pattern)

  • 核心:观察者模式的变种,通过 “事件中心” 解耦发布者和订阅者(多对多)。
  • 场景:
    • 事件总线(如 Vue 的 EventBus)。
    • 自定义事件系统(如 document.addEventListener)。
    • 状态管理库(Redux 的 subscribe)。
// 发布-订阅模式:事件总线
class EventEmitter {
  constructor() {
    this.events = {};
  }
  on(event, callback) {
    this.events[event] = this.events[event] || [];
    this.events[event].push(callback);
  }
  emit(event, data) {
    (this.events[event] || []).forEach(cb => cb(data));
  }
}

const eventEmitter = new EventEmitter()
eventEmitter.on('msg', (data) => console.log(data));
eventEmitter.emit('msg', '发布一条消息');

观察者模式 (Observer Pattern)

  • 核心:对象(Subject)直接维护依赖列表,定义对象间的一对多依赖关系,当一个对象状态变化时,所有依赖者自动收到通知。
  • 场景:
    • 数据响应式系统(Vue 的 Object.defineProperty/Proxy)。
    • MVC 中的 Model-View 同步。
    • 事件监听(addEventListener)
// 观察者模式实现
class Subject {
  constructor() {
    this.observers = [];
  }
  subscribe(observer) {
    this.observers.push(observer);
  }
  notify(data) {
    this.observers.forEach(observer => observer.update(data));
  }
}

class Observer {
  update(data) { console.log('收到数据:', data); }
}
const subject = new Subject();
subject.subscribe(new Observer());
subject.notify('Hello'); // 输出"收到数据: Hello"

工厂模式 (Factory Pattern)

  • 核心:通过工厂函数统一创建相似对象,隐藏具体创建细节。
  • 场景:
    • 动态创建组件(如 React/Vue 的组件工厂)。
    • 根据条件生成不同类实例。
    • 处理不同数据源的适配器。
function createButton(type) {
  if (type === "primary") return new PrimaryButton();
  else return new DefaultButton();
}

// 工厂模式实现
class Button {
  constructor(text) { this.text = text; }
}
class Input {
  constructor(placeholder) { this.placeholder = placeholder; }
}
const UIComponentFactory = {
  create: (type, options) => {
    switch(type) {
      case 'button': return new Button(options.text);
      case 'input': return new Input(options.placeholder);
    }
  }
};
const btn = UIComponentFactory.create('button', { text: '点击' });

策略模式 (Strategy Pattern)

  • 核心:定义一系列算法,封装并按需切换,避免多重条件判断。
  • 场景:
    • 表单验证规则(不同字段对应不同验证策略)。
    • 支付方式切换(支付宝、微信等)。
// 策略模式:支付方式切换
const strategies = {
  alipay: () => "支付宝支付",
  wechat: () => "微信支付",
};
const executePayment = (method) => strategies[method]();

// 策略模式:表单验证
const validators = {
  required: (val) => val.trim() !== '',
  email: (val) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val)
};
const validate = (value, strategy) => validators[strategy](value);
validate('test@example.com', 'email'); // true

代理模式 (Proxy Pattern)

  • 核心:通过代理对象控制对目标对象的访问。
  • 场景:
    • 数据拦截(ES6 Proxy 实现响应式)。
    • 图片懒加载(代理 Image 对象)。
    • API 请求缓存。
const target = {};
const proxy = new Proxy(target, {
  get(obj, key) {
    console.log("访问属性:", key);
    return obj[key];
  },
});

// 代理模式:图片懒加载代理
const imageProxy = {
  setSrc: (img, src) => {
    img.src = 'loading.png'; // 先显示占位图
    const realImg = new Image();
    realImg.onload = () => { img.src = src; }; // 加载完成后替换
    realImg.src = src;
  }
};

装饰器模式 (Decorator Pattern)

  • 核心:动态扩展对象功能,不改变原对象。
  • 场景:
    • 高阶组件(HOC)包装 React 组件。
    • ES7 装饰器语法(@log 日志注入)。
// React HOC 示例
const withLogger = (Component) => (props) => {
  console.log("组件渲染:", props);
  return <Component {...props} />;
};

适配器模式 (Adapter Pattern)

  • 核心:将一个类的接口转换为另一个接口,使不兼容的接口可以协同工作
  • 场景:
    • 兼容不同 API 的数据格式(如后端接口变更)。
    • 新旧 API 兼容(如将回调式接口适配为 Promise 接口)
    • 旧代码与新系统集成。
// 旧版 API 适配到新接口
const legacyApi = { getUser: () => [{ id: 1, name: "John" }] };
const newApiAdapter = {
  fetchUsers: () => legacyApi.getUser().map(user => ({ uid: user.id, fullName: user.name })),
};

// 适配器模式:将回调API适配为Promise
const oldApi = {
  fetchData: (callback) => {
    setTimeout(() => callback('数据'), 1000);
  }
};
// 适配器
const adaptToPromise = (fn) => {
  return () => new Promise(resolve => fn(resolve));
};
const newApi = { fetchData: adaptToPromise(oldApi.fetchData) };
newApi.fetchData().then(data => console.log(data));

组合模式 (Composite Pattern)

  • 核心:将对象组合成树形结构,统一处理整体和部分。
  • 场景:
    • UI 组件树(如 DOM 结构、React/Vue 组件嵌套)。
    • 递归渲染菜单/文件夹结构。
// React 递归组件示例
const TreeNode = ({ children }) => (
  <ul>
    {children.map((node) => (
      <li key={node.id}>
        {node.name}
        {node.children && <TreeNode children={node.children} />}
      </li>
    ))}
  </ul>
);

其他重要模式

  • 状态模式 (State Pattern):管理组件状态机(如登录状态切换)。
  • 命令模式 (Command Pattern):封装操作(如撤销/重做功能)。
  • 享元模式 (Flyweight Pattern):共享细粒度对象(如表格重复单元格优化)。