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

112 阅读2分钟

发布订阅

发布订阅模式需要两个方法,发布订阅,发布和订阅是完全解耦的。

// 事件注册后可以手动触发去执行回调的一种思想
//    @1 发布者模式维护的是一个回调函数列表
let event = {
  _arr: [],
  on(key, fn) {
    this._arr.push({ key, fn });
  },
  emit(key, data) {
    var curCb = this._arr.find(itm => itm.key == key).fn; // 找到对应的回调

    curCb && curCb(data);
  }
}

event.on('first', data => {
  console.log(`${ data }`);
});

event.on('second', data => {
  console.log(`${ data }`);
});

event.emit('first', '发送第一个数据');
event.emit('second', '发送第二个数据');

// 发送第一个数据
// 发送第二个数据

观察者模式

观察者模式是基于发布订阅的,而且观察者模式是基于类来实现的,当订阅的事件状态发生改变,会自动通知观察者,实现回调方法立即执行。

// 观察者模式需要两个类 观察者和被观察者
//   @1 观察者模式维护的是一个观察者列表,它的回调在原型上「update」

class Subs { // 被观察者
  constructor(name) {
    this.name = name;
    this.watchers = []; // 观察者列表 而不是事件列表啦
    this.state = '开心😊';
  }

  attach(watcher) { 
    this.watchers.push(watcher);
  }

  setState(newState) { // 改变被观察者状态
    this.state = newState;
    // 自动执行观察者的回调方法
    this.watchers.forEach(wacher => wacher.update(newState));
  }
}

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

  update(state) { // 被观察者状态变化了,需要更新啦
    console.log(`${ this.name }知道啦: 当前宝宝状态是 ${ state }`);
  }
}

var baby = new Subs('宝宝');
var o1 = new Observer('爸爸');
var o2 = new Observer('妈妈');

baby.attach(o1);
baby.attach(o2);

baby.setState('不开心😣');

// 爸爸知道啦: 当前宝宝状态是 不开心😣
// 妈妈知道啦: 当前宝宝状态是 不开心😣

二者之间的区别

  1. 发布订阅模式维护了一个回调函数的列表,每次触发执行该函数,而观察者模式维护了一个观察者列表,每次触发去调用观察者继承自类的 update 方法。
  2. 发布订阅是手动触发回调,观察者模式只要被观察者状态变化,则主动通知观察者去执行回调。