Skip to content

前端常用设计模式详解

以下是前端开发中常用的设计模式,涵盖特点、适用场景及源码实现(JavaScript示例):

1. 单例模式 (Singleton)

  • 特点:
    • 确保类只有一个实例
    • 提供全局访问点
    • 延迟初始化(使用时才创建)
  • 适用场景:
    • 全局状态管理(如 Redux Store)
    • 共享资源(如数据库连接池)
    • 缓存系统
  • 源码实现:
javascript
class Singleton {
  static instance;
  
  constructor() {
    if (Singleton.instance) return Singleton.instance;
    this.data = "Initial Data";
    Singleton.instance = this;
  }
  
  updateData(newData) {
    this.data = newData;
  }
}

// 使用示例
const instance1 = new Singleton();
const instance2 = new Singleton();
console.log(instance1 === instance2); // true

2. 观察者模式 (Observer)

  • 特点:
    • 一对多的依赖关系
    • 主题状态变化时自动通知观察者
    • 松耦合(主题和观察者互不依赖)
  • 适用场景:
    • 事件处理系统(如 DOM 事件)
    • 响应式数据绑定(Vue/React 状态更新)
    • 实时数据推送(WebSocket 消息)
  • 源码实现:
javascript
class Subject {
  observers = [];
  
  addObserver(observer) {
    this.observers.push(observer);
  }
  
  notify(data) {
    this.observers.forEach(observer => observer.update(data));
  }
}

class Observer {
  update(data) {
    console.log(`Received data: ${data}`);
  }
}

// 使用示例
const subject = new Subject();
const observer1 = new Observer();
subject.addObserver(observer1);
subject.notify("State changed!"); // 触发 observer1.update()

1. 工厂模式 (Factory)

  • 特点:
    • 封装对象创建逻辑
    • 通过统一接口创建不同类型对象
    • 解耦调用方与具体类
  • 适用场景:
    • 动态创建 UI 组件(如按钮/输入框)
    • 跨平台对象生成(不同环境返回不同实现)
    • 复杂对象初始化(带依赖注入)
  • 源码实现:
javascript
class ButtonFactory {
  createButton(type) {
    switch (type) {
      case "primary":
        return new PrimaryButton();
      case "secondary":
        return new SecondaryButton();
      default:
        throw new Error("Invalid button type");
    }
  }
}

class PrimaryButton {
  render() {
    return "<button class='primary'>Submit</button>";
  }
}

// 使用示例
const factory = new ButtonFactory();
const button = factory.createButton("primary");
button.render();

4. 装饰器模式 (Decorator)

  • 特点:
    • 扩展对象动态添加功能
    • 不修改原对象结构
    • 多层装饰嵌套
  • 适用场景:
    • 扩展组件功能(如高阶组件 HOC)
    • 添加日志/权限校验等横切关注点
    • 浏览器 API 增强(如 fetch 拦截)
  • 源码实现:
javascript
function withLogger(Component) {
  return class extends React.Component {
    componentDidMount() {
      console.log(`Component ${Component.name} mounted`);
    }
    render() {
      return <Component {...this.props} />;
    }
  };
}

// React组件使用
class MyComponent extends React.Component { ... }
const EnhancedComponent = withLogger(MyComponent);

5. 策略模式 (Strategy)

  • 特点:
    • 封装可互换的算法族
    • 运行时动态切换策略
    • 避免多重条件语句
  • 适用场景:
    • 表单验证规则切换
    • 支付方式选择(支付宝/微信/银行卡)
    • 数据排序算法切换
  • 源码实现:
javascript
const strategies = {
  add: (a, b) => a + b,
  subtract: (a, b) => a - b,
  multiply: (a, b) => a * b
};

class Calculator {
  execute(strategy, a, b) {
    return strategies[strategy](a, b);
  }
}

// 使用示例
const calc = new Calculator();
console.log(calc.execute("add", 5, 3)); // 8

6. 代理模式 (Proxy)

  • 特点:
    • 控制对原对象的访问
    • 添加额外逻辑(如缓存/权限校验)
    • 与原对象实现相同接口
  • 适用场景:
    • 图片懒加载
    • API 请求缓存
    • 访问控制(如权限验证)
  • 源码实现:
javascript
class ImageProxy {
  constructor(url) {
    this.url = url;
    this.realImage = null;
  }
  
  display() {
    if (!this.realImage) {
      this.realImage = new RealImage(this.url);
      console.log("Loading image...");
    }
    this.realImage.display();
  }
}

class RealImage {
  constructor(url) { this.url = url; }
  display() { console.log(`Displaying: ${this.url}`); }
}

// 使用示例
const proxy = new ImageProxy("photo.jpg");
proxy.display(); // 首次加载
proxy.display(); // 直接显示(已缓存)

选择建议:

模式何时使用
单例模式需要全局唯一实例时
观察者模式组件间解耦的实时通信
工厂模式动态创建复杂对象
装饰器模式需动态扩展功能且避免修改原代码
策略模式需在运行时切换算法
代理模式控制访问或添加中间逻辑

实际项目中常组合使用(如 React 的 HOC=工厂+装饰器,Redux=单例+观察者)。建议根据具体需求灵活选择,避免过度设计。

Last updated: