发布订阅模式和观察者模式

发布订阅模式和观察者模式
最新回答
酱紫—喵

2023-09-22 00:50:17

发布订阅模式和观察者模式是两种常见的软件设计模式,它们都用于处理对象间的通信,但在实现方式和应用场景上有所不同。以下是对这两种模式的详细比较和总结:

发布订阅模式

核心思想

  • 发布订阅模式通过一个事件中心(或称为消息代理)来管理订阅者和发布者之间的通信。
  • 订阅者向事件中心订阅特定类型的事件,并注册回调函数。
  • 发布者向事件中心发布事件,事件中心负责找到所有订阅了该事件的订阅者,并调用它们的回调函数。

特点

  • 解耦:发布者和订阅者之间不需要知道对方的存在,它们只与事件中心交互。
  • 灵活性:可以动态地添加或删除订阅者,而不需要修改发布者的代码。
  • 可扩展性:易于添加新的事件类型和订阅者,系统扩展性强。

代码示例

class EventEmitter { constructor() { this.subs = {}; // 事件中心 } $on(eventType, handler) { this.subs[eventType] = this.subs[eventType] || []; this.subs[eventType].push(handler); } $emit(eventType) { if (this.subs[eventType]) { this.subs[eventType].forEach(handler => handler()); } }}const em = new EventEmitter();em.$on('a', () => console.log('第一次订阅事件 a'));em.$on('a', () => console.log('第二次订阅事件 a'));em.$emit('a'); // 输出两次订阅的日志观察者模式

核心思想

  • 观察者模式中,观察者(或称为监听者)直接订阅被观察者(或称为主题)。
  • 当被观察者的状态发生变化时,它会直接通知所有观察者,调用它们的更新方法。

特点

  • 紧耦合:观察者和被观察者之间通常存在直接的引用关系,被观察者需要知道观察者的存在。
  • 实时性:状态变化会立即通知所有观察者,响应速度快。
  • 适用于一对一或一对多的通知场景:如GUI中的事件处理、模型-视图-控制器(MVC)模式中的视图更新等。

代码示例

class Dep { constructor() { this.subs = []; // 存储观察者 } addSub(sub) { if (sub && sub.update) { this.subs.push(sub); } } notify() { this.subs.forEach(sub => sub.update()); }}class Watcher { update() { console.log('~ ~ ~ update'); }}const dep = new Dep();const watcher = new Watcher();dep.addSub(watcher);dep.notify(); // 输出: ~ ~ ~ update总结
  • 发布订阅模式更侧重于事件的发布和订阅,通过事件中心实现发布者和订阅者的解耦,适用于需要高度灵活性和可扩展性的场景。
  • 观察者模式则更侧重于观察者和被观察者之间的直接交互,被观察者状态变化时直接通知观察者,适用于需要实时响应和紧耦合的场景。

在实际应用中,两种模式可以结合使用,以发挥各自的优势。例如,在一个复杂的系统中,可以使用发布订阅模式来处理全局事件,同时使用观察者模式来处理特定组件间的实时通信。