白话JS观察者模式和发布订阅模式

从对观察者模式和发布订阅模式有疑问开始,连续看了好几篇文章,最后疑惑依然存在,这到底哪里不一样??进一步研究和思考后才搞明白,我决定用最大白话最直观的代码方式来记录下来,以便未来再次忘记时来翻阅。

观察者模式和发布订阅模式最大的区别就是调度的方式不同,观察者模式是由目标直接调度,发布订阅模式由调度中心调度,这句话比较抽象,用最简单的代码表现一下大概是下面这样:

  1. 纯享版观察者模式
var Subject = {
  observers: [], //观察者列表
  add(callback) {
    //添加观察者
    this.observers.push(callback);
  },
  remove() {}, //移除观察者
  notify() {
    //通知所有观察者
    this.observers.forEach((fn) => fn());
  },
};
  1. 纯享版发布订阅模式
var Event = {
  _listeners: {}, //订阅通道
  on: function (eventName, callback) {
    if (!this._listeners[eventName]) this._listeners[eventName] = [];
    this._listeners[eventName].push(callback);
  },
  emit: function (eventName) {
    if (this._listeners[eventName]) {
      this._listeners[eventName].forEach((callback) => {
        callback(...[].slice.call(arguments, 1));
      });
    }
  },
};

//测试
Event.on('test', function (result) {
  console.log(result);
});
Event.on('test', function () {
  console.log('test');
});
Event.emit('test', 'hello world'); // 输出 'hello world' 和 'test'

从上面两个纯享版代码可以看出来,观察者模式就是维护一个观察者列表,当需要时,直接广播通知(遍历整个观察者列表);发布订阅模式是维护一个订阅通道,所谓订阅通道就是一个按事件名称存储订阅列表的地方,当某个事件名称被触发时,会在订阅通道中查找对应的订阅者列表,所以说白了发布订阅模式就是若干个观察者模式的集合,这样够直白了吧。