定义:

  • 定义对象间的一种一对多的依赖关系
  • 当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新

类比:就像你订阅了某个博客,当有新的文章发布时,你会收到通知

应用场景

  • 一个对象的改变需要触发其他对象的改变时
  • 需要动态地增加或减少观察者时

优缺点

  • 优点
    • 建立对象之间的动态联动
    • 支持广播通信
  • 缺点
    • 可能引起循环依赖或触发频繁的更新
    • 不容易确定哪些对象依赖于哪些其他对象

观察者模式和发布-订阅模式的区别

观察者模式发布-订阅模式
角色关系观察者和主题之间直接交互发布者和订阅者之间通过调度中心(或事件总线)进行通信
解耦程度解耦程度较低。观察者需要知道主题,主题需要记录观察者解耦程度较高。发布者和订阅者之间没有直接的依赖关系
异步处理更适合同步处理,实现较为简单更适合异步处理,可以跨线程、跨进程甚至跨系统进行通信。

实现代码

// 观察者接口
interface Observer {
  update(subject: Subject): void;
}
 
// 被观察者类
class Subject {
  private observers: Observer[] = [];
  private state: number;
 
  public getState(): number {
    return this.state;
  }
 
  public setState(state: number): void {
    this.state = state;
    this.notifyAllObservers();
  }
 
  public attach(observer: Observer): void {
    this.observers.push(observer);
  }
 
  public notifyAllObservers(): void {
    for (const observer of this.observers) {
      observer.update(this);
    }
  }
}
 
// 具体观察者类
class ConcreteObserverA implements Observer {
  public update(subject: Subject): void {
    if (subject.getState() < 3) {
      console.log('ConcreteObserverA: Reacted to the event.');
    }
  }
}
 
class ConcreteObserverB implements Observer {
  public update(subject: Subject): void {
    if (subject.getState() >= 3) {
      console.log('ConcreteObserverB: Reacted to the event.');
    }
  }
}
 
// 客户端代码
const subject = new Subject();
 
const observer1 = new ConcreteObserverA();
subject.attach(observer1);
 
const observer2 = new ConcreteObserverB();
subject.attach(observer2);
 
subject.setState(2);
subject.setState(3);