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


观察者模式

观察者模式(Observer Pattern)

  • 观察者模式定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知,并自动更新。观察者模式属于行为型模式,行为型模式关注的是对象之间的通讯,观察者模式就是观察者和被观察者之间的通讯。
  • 观察者模式有一个别名叫“发布-订阅模式”,或者说是“订阅-发布模式”,订阅者和订阅目标是联系在一起的,当订阅目标发生改变时,逐个通知订阅者

流程

  • 目标<=>观察者
  • 观察者观察目标(监听目标)-> 目标发生变化-> 目标主动通知观察者

例子

  • 拍卖的时候,拍卖师观察最高标价,然后通知给其他竞价者竞价,即“一对多”的依赖关系(一个拍卖师多个竞价者)

应用

  • Vue数据双向绑定

实现

class Subject {
  constructor() {
    this.observers = [];
  }
  add(observer) {
    this.observers.push(observer);
  }
  notify(...args) {
    this.observers.forEach(observer => observer.update(...args));
  }
}
class Observer {
  update(...args) {
    console.log(...args);
  }
}
 
// 创建观察者ob1
let ob1 = new Observer();
// 创建观察者ob2
let ob2 = new Observer();

// 创建目标sub
let sub = new Subject();
// 目标sub添加观察者ob1 (目标和观察者建立了依赖关系)
sub.add(ob1);
// 目标sub添加观察者ob2
sub.add(ob2);
// 目标sub触发SMS事件(目标主动通知观察者)
sub.notify('I fired `SMS` event');

发布订阅模式

发布订阅模式(Pub-Sub Pattern)

  • 发布订阅模式中,发送者不会将消息直接发送给订阅者,这意味着发布者和订阅者不知道彼此的存在。在发布者和订阅者之间存在第三个组件,称为调度中心或事件通道,它维持着发布者和订阅者之间的联系,过滤所有发布者传入的消息并相应地分发它们给订阅者
  • 发布订阅模式是在观察者模式的基础上做的优化升级

流程

  • 发布者->事件中心<=>订阅者
  • 订阅者需要向事件中心订阅指定的事件 -> 发布者向事件中心发布指定事件内容 -> 事件中心通知订阅者 -> 订阅者收到消息(可能是多个订阅者)

例子

  • 你在微博上关注了A,同时其他很多人也关注了A,那么当A发布动态的时候,微博就会为你们推送这条动态。A就是发布者,你是订阅者,微博就是调度中心,你和A是没有直接的消息往来的,全是通过微博来协调的(你的关注,A的发布动态)

应用

  • vue中的事件总线,$emit和$on, $on用来订阅事件,$emit用来发布订阅的事件

实现

class PubSub {
  constructor() {
    // 事件中心/调度中心
    this.subscribers = [];
  }
  // 订阅
  subscribe(topic, callback) {
    let callbacks = this.subscribers[topic];
    if (!callbacks) {
      this.subscribers[topic] = [callback];
    } else {
      callbacks.push(callback);
    }
  }
  // 发布
  publish(topic, ...args) {
    let callbacks = this.subscribers[topic] || [];
    callbacks.forEach(callback => callback(...args));
  }
}
 
// 创建事件调度中心,为订阅者和发布者提供调度服务
let pubSub = new PubSub();
// A订阅了SMS事件(A只关注SMS本身,而不关心谁发布这个事件)
pubSub.subscribe('SMS', console.log);
// B订阅了SMS事件
pubSub.subscribe('SMS', console.log);
// C发布了SMS事件(C只关注SMS本身,不关心谁订阅了这个事件)
pubSub.publish('SMS', 'I published `SMS` event');

区别

  • 发布-订阅模式是面向调度中心编程的,而观察者模式则是面向目标和观察者编程的。前者用于解耦发布者和订阅者,后者用于耦合目标和观察者

  目录