从东京奥运会看js设计模式之发布订阅模式

371 阅读3分钟

这是我参与8月更文挑战的第2天,活动详情查看:8月更文挑战

开篇废话:本篇文章介绍发布-订阅模式,想必很多人听说过有一种观察者模式,网上既有资料说这是两种不同的设计模式,也有说这是一种模式,我倾向于认同他们是同一种设计模式。不必过于纠结

开篇楔子:东京奥运会已经开幕有一段时间了,在本次奥运会上我国的奥运健儿们取得了非常不错的成绩,截止至目前(2021.08.05),我国取得了34金24银16铜,在上班时间也时刻关注着比赛详情,但对于打工人来说摸鱼看完整比赛可能做不到,但是偶尔刷新查看一下奥运奖牌榜的事没少干。然后我就在想要是谁能及时通知我奖牌数的变化就好了,假设juejiin提供了奖牌数据,我点击关注订阅后,然后juejiin实时给我推送最新的奖牌榜,这不就是一个订阅-发布模式吗

用代码实现发布-订阅模式,获取奥运奖牌数,主要有三步

  • 保存所有订阅信息, eventList
  • 提供订阅方法,将订阅事件保存到eventList中
  • 提供一个发布方法,将所有订阅的事件发布出去
class Emitter {
  constructor() {
    // 保存所有订阅的事件
    this.eventList = {};
  }
  // 订阅事件:事件名称,事件处理函数
  subscribe(eventName, fn) {
    if (!this.eventList[eventName]) {
      this.eventList[eventName] = [];
    }
    this.eventList[eventName].push(fn);
  }
  // 发布事件:事件名称,参数
  publish(eventName, ...args) {
    const fns = this.eventList[eventName];
    if (!fns || fns.length === 0) {
      return;
    }
    fns.forEach((fn) => {
      fn.apply(this, args);
    });
  }
}

以上就是一个简单的发布订阅模式的实现,写一段测试代码

const juejiin = new Emitter();
juejiin.subscribe("china-medal", function (medals) {
  console.log("中国奖牌数:", medals);
});

juejiin.publish("china-medal", "34金24银16铜");
juejiin.publish("china-medal", "43金30银27铜");

输出结果:

中国奖牌数: 34金24银16铜
中国奖牌数: 43金30银27铜

如果奥运会结束,我就不需要再关注奖牌数,这时需要一个取消订阅事件remove

class Emitter {
 // 省略其他代码xxx
  remove(eventName, fn) {
    const fns = this.eventList[eventName];
    if (!fns || fns.length === 0) {
      return;
    }
    const idx = fns.findIndex((item) => item === fn);
    fns.splice(idx, 1);
  }
}

继续来一段测试代码,测试能否正确取消订阅

const juejiin = new Emitter();
const fn = function (medals) {
  console.log("中国奖牌数:", medals);
};
juejiin.subscribe("china-medal", fn);

juejiin.publish("china-medal", "34金24银16铜");
juejiin.publish("china-medal", "43金30银27铜");

setTimeout(() => {
  juejiin.remove("china-medal", fn);
  juejiin.publish("china-medal", "奥运会结束啦,不能发布了");
}, 1000);

还不错,这个发布订阅功能已经比较齐全了。

如果想看更多有关发布订阅模式的应用,请看我以前的文章: