单例模式确保类唯一实例并提供全局访问,观察者模式实现一对多响应式通信;二者可结合为单例事件总线,兼顾唯一性与松耦合通信。

单例模式确保一个类只有一个实例,并提供全局访问点;观察者模式定义对象间一对多依赖关系,当一个对象状态改变时,所有依赖它的对象都会自动收到通知。两者都用于解耦和复用,但解决的问题不同:单例关注“唯一性”,观察者关注“响应式通信”。
单例模式:怎么保证只创建一次?
核心是控制构造逻辑,不让外部随意 new 实例。常见做法是用闭包或静态属性缓存实例,首次调用时创建,之后直接返回已有实例。
- 用闭包封装私有实例变量,暴露一个获取实例的方法
- ES6 类写法中可在类内部用 static 属性存储实例,constructor 检查是否已存在
- 注意:单例不是“全局变量”,而是受控的、延迟初始化的唯一对象
- 典型场景:日志器、配置管理器、状态仓库(如 Redux store 的初始化)
观察者模式:如何让多个对象监听同一事件?
关键角色有“被观察者(Subject)”和“观察者(Observer)”。Subject 维护一个观察者列表,提供订阅(subscribe)、取消订阅(unsubscribe)、通知(notify)三个基本操作。
- 订阅时把回调函数或观察者对象加入列表
- 触发事件时遍历列表,依次执行每个观察者的回调
- 可扩展支持事件类型(如 on('click', fn))、传递参数、异步通知等
- 现代实践中常被 EventEmitter、RxJS、Vue/React 的响应式系统替代,但原理一致
两个模式可以一起用吗?
可以。比如用单例实现一个全局事件总线(EventBus),它本身是唯一的,同时具备观察者功能:任何模块都能 subscribe 到它,也能 emit 事件通知其他模块。
立即学习“Java免费学习笔记(深入)”;
- 这样既避免多个事件中心导致混乱,又实现松耦合通信
- 注意避免内存泄漏:订阅后记得在合适时机 unsubscribe
- 实际项目中,优先考虑框架内置方案(如 Vue 的 $emit / $on,或 React 的 Context + useReducer)
不复杂但容易忽略细节:单例要防多线程(JS 单线程所以通常不用考虑),观察者要注意执行顺序和错误隔离。理解本质比死记代码更重要。










