观察者模式与发布订阅模式的异同

27 阅读2分钟

1. 引言

观察者模式(Observer Pattern)和发布订阅模式(Publish-Subscribe Pattern)都是常见的设计模式,用于处理对象之间的依赖关系和通信。虽然它们在某些方面相似,但在实现方式和应用场景上存在显著差异。

2. 概述

2.1 观察者模式

观察者模式定义了一种一对多的依赖关系,当目标对象(Subject)的状态发生改变时,它的所有依赖者(Observers)都会被通知并自动更新。观察者模式通常用于事件驱动的系统,如用户界面的数据绑定、股票价格更新等。

核心角色:

  • Subject(目标对象) :持有观察者的引用,当自身状态变化时,通知所有观察者。
  • Observer(观察者) :当目标对象的状态变化时,主动获取目标对象的更新。
erDiagram
  "目标对象" ||--o{ "观察者": "通知"
  "观察者" }|..|{ "目标对象" : "观察"

2.2 发布订阅模式

发布订阅模式通过引入一个中介者(Event Center)来解耦发布者和订阅者之间的直接联系。发布者并不知道是否有订阅者,订阅者也不需要直接与发布者交互。事件中心处理消息的分发,使得发布者和订阅者能够独立工作。

核心角色:

  • Publisher(发布者) :发布消息,但不关心是否有订阅者。
  • Subscriber(订阅者) :关注特定事件的消息,并在事件发生时做出反应。
  • Event Center(事件中心) :作为中介,负责消息的发布和分发,处理事件的订阅和取消订阅。
erDiagram
  "发布者" ||--o{ "事件" : "触发"
  "订阅者" ||--o{ "事件" : "监听"
  "事件" ||--o{ "事件中心" : "管理"

3. 代码示例

观察者模式(Observer Pattern)

// 目标对象(Subject)
class Subject {
  constructor() {
    this.observers = [];
  }

  // 添加观察者
  addObserver(observer) {
    this.observers.push(observer);
  }

  // 移除观察者
  removeObserver(observer) {
    this.observers = this.observers.filter(o => o !== observer);
  }

  // 通知所有观察者
  notify() {
    this.observers.forEach(observer => observer.update());
  }
}

// 观察者(Observer)
class Observer {
  constructor(name) {
    this.name = name;
  }

  // 接收通知的方法
  update() {
    console.log(`${this.name} 收到通知`);
  }
}

// 使用示例
const subject = new Subject();
const observer1 = new Observer('观察者1');
const observer2 = new Observer('观察者2');

subject.addObserver(observer1);
subject.addObserver(observer2);

subject.notify();
// 输出:
// 观察者1 收到通知
// 观察者2 收到通知

发布订阅模式(Publish-Subscribe Pattern)

// 事件中心(Event Center)
class EventCenter {
  constructor() {
    this.events = {};
  }

  // 订阅事件
  subscribe(event, callback) {
    if (!this.events[event]) {
      this.events[event] = [];
    }
    this.events[event].push(callback);
  }

  // 发布事件
  publish(event, data) {
    if (this.events[event]) {
      this.events[event].forEach(callback => callback(data));
    }
  }

  // 取消订阅事件
  unsubscribe(event, callback) {
    if (this.events[event]) {
      this.events[event] = this.events[event].filter(cb => cb !== callback);
    }
  }
}

// 使用示例
const eventCenter = new EventCenter();

function subscriber1(data) {
  console.log(`订阅者1 收到消息:${data}`);
}

function subscriber2(data) {
  console.log(`订阅者2 收到消息:${data}`);
}

eventCenter.subscribe('news', subscriber1);
eventCenter.subscribe('news', subscriber2);

eventCenter.publish('news', '新消息发布');
// 输出:
// 订阅者1 收到消息:新消息发布
// 订阅者2 收到消息:新消息发布

主要区别:

  1. 耦合度:

    • 观察者模式中,目标对象和观察者之间是直接关联的,目标对象需要维护观察者列表,观察者也需要知道目标对象的存在。
    • 发布订阅模式通过引入事件中心,发布者和订阅者之间没有直接关联,解耦性更强。
  2. 角色数量:

    • 观察者模式通常只有目标对象和观察者两个角色。
    • 发布订阅模式引入了事件中心,增加了一个中介角色。
  3. 使用场景:

    • 观察者模式适用于一对多的场景,如事件监听。
    • 发布订阅模式适用于需要解耦的场景,如消息队列。