登录
首页 >  文章 >  前端

JavaScript常用设计模式解析:单例与观察者

时间:2026-02-17 12:52:33 500浏览 收藏

本文深入解析了JavaScript中最常用且实用的两大设计模式——单例模式与观察者模式,不仅阐明其核心思想与典型应用场景(如配置管理、状态同步、UI更新),还通过清晰易懂的ES6类实现代码展示了如何手写可靠、可维护的模式实例;同时精准辨析了观察者模式与发布-订阅模式的本质区别,并指出在现代前端开发中,借助ES模块天然单例特性或响应式框架/状态库即可优雅落地,避免过度设计,兼顾原理理解与工程实践。

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

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 内部已融合多种模式,无需重复造轮子

以上就是本文的全部内容了,是否有顺利帮助你解决问题?若是能给你带来学习上的帮助,请大家多多支持golang学习网!更多关于文章的相关知识,也可关注golang学习网公众号。

资料下载
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>