观察者模式中主题直接通知观察者,发布订阅模式通过事件中心解耦通信。前者适用于对象间紧密关联,如Model与View同步;后者适合跨模块通信,如Vue事件总线。两者均需注意取消订阅以避免内存泄漏。

观察者模式和发布订阅模式在JavaScript中常用于解耦组件之间的通信。虽然两者看起来相似,但它们的实现机制和使用场景略有不同。下面分别介绍这两种模式的核心思想与代码实现。
观察者模式(Observer Pattern)
观察者模式定义了一种一对多的依赖关系:当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。
在这个模式中,被观察的对象(称为“主题”或Subject)维护一个观察者列表,并在状态变化时主动通知它们。
实现步骤:
立即学习“Java免费学习笔记(深入)”;
- Subject 提供添加、删除和通知观察者的方法
- Observer 实现一个更新方法,用于接收通知
- Subject 状态变化时,遍历观察者列表并调用其 update 方法
代码示例:
addObserver(observer) { this.observers.push(observer); }
removeObserver(observer) { this.observers = this.observers.filter(obs => obs !== observer); }
notify(data) { this.observers.forEach(observer => observer.update(data)); } }
class Observer { constructor(name) { this.name = name; }
update(data) {
console.log(${this.name} 收到通知:, data);
}
}
// 使用示例 const subject = new Subject(); const obs1 = new Observer('观察者A'); const obs2 = new Observer('观察者B');
subject.addObserver(obs1); subject.addObserver(obs2);
subject.notify('状态已更新!'); // 输出: // 观察者A 收到通知:状态已更新! // 观察者B 收到通知:状态已更新!
发布订阅模式(Publish-Subscribe Pattern)
发布订阅模式引入了事件通道(或事件中心),发布者和订阅者之间没有直接引用。消息通过事件中心进行中转,实现更彻底的解耦。
与观察者模式不同,发布者不直接通知订阅者,而是将消息推送给事件中心,由事件中心分发给所有订阅该事件的消费者。
核心角色:
- Publisher:发布事件
- Subscriber:订阅感兴趣的事件
- Event Channel:负责事件的注册、触发和管理
代码示例:
```javascript class EventCenter { constructor() { this.events = {}; } // 订阅事件 on(event, callback) { if (!this.events[event]) { this.events[event] = []; } this.events[event].push(callback); } // 发布事件 emit(event, data) { if (this.events[event]) { this.events[event].forEach(callback => callback(data)); } } // 取消订阅 off(event, callback) { if (this.events[event]) { this.events[event] = this.events[event].filter(cb => cb !== callback); } } // 只监听一次 once(event, callback) { const wrapper = (data) => { callback(data); this.off(event, wrapper); }; this.on(event, wrapper); } } // 使用示例 const eventBus = new EventCenter(); eventBus.on('news', (msg) => { console.log('新闻订阅者:', msg); }); eventBus.on('news', (msg) => { console.log('另一位读者:', msg); }); eventBus.on('weather', (info) => { console.log('天气预报:', info); }); eventBus.emit('news', '今天发生了重大事件!'); // 输出: // 新闻订阅者: 今天发生了重大事件! // 另一位读者: 今天发生了重大事件! eventBus.emit('weather', '明天晴,气温25℃'); // 输出:天气预报: 明天晴,气温25℃
观察者模式 vs 发布订阅模式
两者都实现了对象间的松耦合通信,但关键区别在于耦合度和控制权:
- 观察者模式中,Subject 直接管理 Observer 列表,两者存在直接依赖
- 发布订阅模式通过事件中心中介,发布者和订阅者完全不知道对方的存在
- 发布订阅更适合复杂系统中的跨模块通信,如Vue的事件总线、Node.js的 EventEmitter
- 观察者模式更适用于对象间紧密关联的场景,如MVC中的Model与View
基本上就这些。理解它们的区别有助于在实际项目中选择合适的通信机制。不复杂但容易忽略细节,比如取消订阅和内存泄漏问题。










