javascript中的设计模式是什么_常见模式如观察者模式如何实现?

JavaScript设计模式是基于语言特性的可复用组织思想,非语法特性;包括观察者模式(一对多依赖)、发布-订阅模式(通过事件总线解耦)、单例模式(闭包实现唯一实例)、工厂模式(灵活创建对象),重在适配JS特性与实际场景。

JavaScript 中的设计模式是解决常见编程问题的可复用结构化方案,不是语法特性,而是基于语言特性的组织思想。它利用 JS 的函数一等公民、闭包、原型链、事件机制等能力,让代码更易维护、扩展和协作。

观察者模式(Observer Pattern)

核心是实现对象间的一对多依赖关系:当一个对象状态改变,所有依赖它的对象自动收到通知并更新。JS 原生事件系统(如 addEventListener / dispatchEvent)就是典型应用,也可手动实现轻量级版本。

手动实现要点:

  • 定义“被观察者”(Subject):维护订阅者列表,提供 subscribeunsubscribenotify 方法
  • 定义“观察者”(Observer):通常是带 update 方法的对象或函数
  • 避免内存泄漏:确保能取消订阅,尤其在组件销毁时(如 React 的 useEffect 清理函数)

简单示例:

class Subject {
  constructor() {
    this.observers = [];
  }
  subscribe(observer) {
    if (typeof observer === 'function') {
      this.observers.push(observer);
    }
  }
  unsubscribe(observer) {
    this.observers = this.observers.filter(fn => fn !== observer);
  }
  notify(data) {
    this.observers.forEach(fn => fn(data));
  }
}

// 使用
const subject = new Subject();
const logObserver = (msg) => console.log('收到:', msg);
subject.subscribe(logObserver);
subject.notify('Hello'); // 输出:收到: Hello
subject.unsubscribe(logObserver);
subject.notify('World'); // 无输出

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

观察者模式的升级版,引入事件总线(Event Bus),解耦发布者与订阅者。两者不直接持有对方引用,全部通过中心调度器通信,适合大型应用或跨模块通信。

关键区别:

  • 观察者模式中,Subject 知道 Observer;Pub/Sub 中,Publisher 和 Subscriber 都只依赖 EventBus
  • Pub/Sub 支持按事件类型(topic)订阅,支持通配符、异步派发、一次*件等扩展

单例模式(Singleton)

确保一个类只有一个实例,并提供全局访问点。JS 中常用闭包或模块模式天然实现,无需复杂锁机制。

常见写法:

// 模块模式(推荐)
const Logger = (function() {
  let instance;
  function init() {
    return {
      log: (msg) => console.log('[LOG]', msg)
    };
  }
  return {
    getInstance: () => {
      if (!instance) instance = init();
      return instance;
    }
  };
})();

// 使用
const logger1 = Logger.getInstance();
const logger2 = Logger.getInstance();
console.log(logger1 === logger2); // true

工厂模式与构造函数/类的区别

工厂模式返回对象,不依赖 new;构造函数和 class 本质是语法糖,仍需 new 调用。工厂更适合创建不同子类型的对象(如根据配置返回不同 API 客户端)。

例如:

function createAPI(type) {
  if (type === 'rest') {
    return { request: () => 'REST call' };
  } else if (type === 'graphql') {
    return { query: () => 'GraphQL query' };
  }
}
const api = createAPI('rest');

设计模式的价值不在套用名称,而在理解问题场景后,选择最贴合 JS 特性、团队习惯和项目规模的组织方式。原生事件、Promise、Proxy、自定义 Hook 等现代实践,很多已内建了经典模式的思想。