观察者模式和发布订阅模式都是设计模式中用来处理对象之间依赖关系的,但它们的实现方式和应用场景有所不同。
-
观察者模式
- 是一种一对多的依赖关系。
- 直接通信:观察者对象直接订阅目标对象(Subject)。当目标对象的状态发生变化时,它会通知所有观察者更新。
- 依赖性强:观察者和被观察者之间存在强耦合关系。
示例:
- 目标对象(Subject)管理一组观察者(Observers),通过
addObserver()和notifyObservers()等方法通知变化。
// 观察者模式
class Subject {
constructor() {
this.observers = []; // 存储观察者
}
// 添加观察者
addObserver(observer) {
this.observers.push(observer);
}
// 通知所有观察者
notify(data) {
this.observers.forEach(observer => observer.update(data));
}
}
class Observer {
update(data) {
console.log('更新数据:', data);
}
}
const subject = new Subject();
const observer1 = new Observer();
const observer2 = new Observer();
subject.addObserver(observer1);
subject.addObserver(observer2);
subject.notify('状态改变'); // 通知所有观察者
-
发布订阅模式
- 是一种多对多的关系。
- 通过中间件通信:发布者和订阅者之间没有直接联系,而是通过一个事件调度中心(Event Bus)实现解耦。
- 松耦合:发布者无需关心谁订阅了事件,订阅者也无需知道谁发布了事件。
示例:
- 一个中央事件总线(Event Bus)管理订阅和发布。
// 发布订阅模式
class EventBus {
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));
}
}
}
const eventBus = new EventBus();
eventBus.on('event1', data => console.log('订阅者1接收数据:', data));
eventBus.on('event1', data => console.log('订阅者2接收数据:', data));
eventBus.emit('event1', '发布数据'); // 通知所有订阅者
观察者模式 VS 发布订阅模式 的应用场景
观察者模式:如果对象之间存在明确的依赖关系,需要直接通信,选择观察者模式。
- React 的组件更新机制。
- 数据绑定:当模型变化时通知视图(如 Vue 的双向绑定)。
- 浏览器的 DOM 事件监听:
addEventListener。
发布订阅模式:如果需要解耦对象关系或多个模块间需要共享事件,则使用发布订阅模式。
- 前端事件总线(如 Vue 中的
EventBus)。 - Redux 中的订阅与发布。
- 消息中间件(如 Kafka、RabbitMQ)。