javascript的设计模式有哪些_如何实现单例模式和观察者模式

JavaScript常用设计模式包括单例、观察者、工厂、代理等,其中单例确保类唯一实例,适用于配置管理;观察者实现一对多依赖更新,Subject与Observer直接通信,区别于发布-订阅的事件总线解耦。

JavaScript 中常用的设计模式包括单例模式、观察者模式、工厂模式、代理模式、装饰器模式、策略模式、发布-订阅模式(常与观察者混淆但有区别)、命令模式、适配器模式等。其中单例和观察者最常用于前端架构和状态管理。

单例模式:确保一个类只有一个实例

核心是控制构造函数的调用次数,避免重复创建对象。适用于配置管理、全局状态、日志工具、弹窗管理器等场景。

常见实现方式:

  • 闭包 + 静态属性:利用 IIFE 封装私有实例,通过返回的函数暴露唯一入口
  • ES6 Class + 静态实例缓存:在类上挂载 instance 属性,构造前检查是否已存在
  • 模块顶层导出:利用 ES 模块天然单例特性(最简单、推荐)

示例(Class 方式):

class Logger {
  constructor() {
    if (Logger.instance) {
      return Logger.instance;
    }
    this.logs = [];
    Logger.instance = this;
  }
  log(msg) {
    this.logs.push(`[${new Date().toISOString()}] ${msg}`);
  }
}
const logger1 = new Logger();
const logger2 = new Logger();
console.log(logger1 === logger2); // true

观察者模式:定义对象间一对多依赖,当一个对象改变状态,所有依赖者自动更新

典型结构包含 Subject(被观察者)Observer(观察者)。Subject 维护观察者列表,提供添加、移除、通知方法;Observer 实现统一更新接口。

关键点:

  • 观察者需有明确的 update 方法供 Subject 调用
  • Subject 应支持动态增删观察者,避免内存泄漏(尤其在 DOM 或异步场景中)
  • 可扩展为支持事件名、参数透传、取消订阅 token 等

简易实现:

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

class Observer {
  constructor(name) {
    this.name = name;
  }
  update(data) {
    console.log(`${this.name} received:`, data);
  }
}

const subject = new Subject();
const obs1 = new Observer('UI');
const obs2 = new Observer('Logger');

subject.subscribe(obs1);
subject.subscribe(obs2);
subject.notify('data changed'); // 两者都会收到

注意:观察者 vs 发布-订阅

观察者模式中 Subject 和 Observer 是直接引用关系;而发布-订阅通过事件总线(Event Bus)解耦,发布者不关心谁订阅,订阅者也不知谁发布。Vue 的 $emit/$on、Node.js 的 EventEmitter 都属于后者。

实际项目中的简化用法

现代开发中,往往不需要手写完整模式:

  • 单例 → 直接用 ES 模块导出一个对象(import 即共享同一份)
  • 观察者 → 使用 Proxy + 自定义响应式逻辑,或封装成 hook(如 React 的 useSubscription)
  • 状态库如 Redux、Pinia、Zustand 内部已融合多种模式,无需重复造轮子