ES6 class 可简洁实现观察者模式:基础版用 Set 管理观察者,提供 subscribe、unsubscribe、notify;进阶版 EventEmitter 用 Map 支持多事件;业务类可继承并自动通知状态变更,需注意内存泄漏与生命周期管理。

ES6 的 class 可以简洁、清晰地实现观察者模式(Observer Pattern),也就是常说的“订阅-发布”机制。核心是维护一个观察者列表,提供 subscribe(添加)、unsubscribe(移除)和 notify(触发通知)三个关键行为。
基础观察者类(Subject)
这是被观察的对象,负责管理订阅者并广播事件:
- 用
Set存储观察者函数,天然去重、避免重复订阅 -
subscribe(fn)添加观察者,返回一个取消订阅函数(便于使用unsubscribe或自动清理) -
unsubscribe(fn)移除指定观察者 -
notify(data)遍历所有观察者并调用,传入通知数据
示例代码:
class Subject {
constructor() {
this.observers = new Set();
}
subscribe(fn) {
this.observers.add(fn);
return () => this.unsubscribe(fn);
}
unsubscribe(fn) {
this.observers.delete(fn);
}
notify(data) {
this.observers.forEach(fn => fn(data));
}
}
带事件类型的进阶版(支持多事件)
实际项目中通常需要按事件类型区分通知,比如 "user:login" 和 "data:updated"。可扩展为事件中心:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- 用
Map管理不同事件名对应的观察者集合 -
subscribe(event, fn)按事件注册 -
notify(event, data)只通知对应事件的观察者 -
clear(event)或unsubscribeAll(event)清空某事件所有监听器
示例:
class EventEmitter {
constructor() {
this.events = new Map();
}
subscribe(event, fn) {
if (!this.events.has(event)) {
this.events.set(event, new Set());
}
const listeners = this.events.get(event);
listeners.add(fn);
return () => this.unsubscribe(event, fn);
}
unsubscribe(event, fn) {
const listeners = this.events.get(event);
if (listeners) listeners.delete(fn);
}
notify(event, data) {
const listeners = this.events.get(event);
if (listeners) listeners.forEach(fn => fn(data));
}
}
结合类实例的状态变化自动通知
让业务类自身成为 Subject,在关键状态变更时主动 notify。例如一个用户类:
class User extends EventEmitter {
constructor(name) {
super();
this._name = name;
}
get name() {
return this._name;
}
set name(value) {
if (value !== this._name) {
const old = this._name;
this._name = value;
this.notify('nameChanged', { old, new: value });
}
}
}
// 使用
const user = new User('Alice');
user.subscribe('nameChanged', ({ old, new: name }) => {
console.log(`用户名从 ${old} 改为 ${name}`);
});
user.name = 'Bob'; // 输出:用户名从 Alice 改为 Bob
注意事项与优化建议
- 观察者函数应尽量轻量;若需异步或防抖,由订阅方自行处理,而非在
notify中封装 - 注意内存泄漏:组件销毁(如 React 卸载、Vue
beforeUnmount)时务必调用unsubscribe - 可增加
once(event, fn)方法,实现只执行一次的订阅 - 生产环境建议加类型检查(如判断
fn是否为函数)和错误边界(try/catch包裹单个观察者调用)
不复杂但容易忽略的是生命周期管理——订阅容易,忘记取消才是常见 bug 来源。

















