JavaScript设计模式(五):发布-订阅模式

138 阅读1分钟

定义

发布-订阅模式:又称为观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态改变时,所有依赖于它的对象都将得到通知。

这个有点类似于我们平时关注的公众号,公众号发布消息,所有订阅了的人,都会收到消息。

实现一个简单的发布订阅模式

const Event = function () {
  this.obj = {}
}

Event.prototype.on = function (eventType, fn) {
  if (!this.obj[eventType]) {
    this.obj[eventType] = []
  }
  this.obj[eventType].push(fn)
}

Event.prototype.emit = function () {
  const eventType = Array.prototype.shift.call(arguments)
  const arr = this.obj[eventType]
  for (let i = 0; i < arr.length; i++) {
    arr[i].apply(arr[i], arguments)
  }
}

const ob = new Event()

ob.on('say', function (msg) {    // 订阅
  console.log(msg)               // hello
})

ob.emit('say', 'hello')          // 发布

当我们将原本emit里触发的函数缓存下来,放到on中触发,就可以实现先发布函,后订阅。就像下面这样。

const Event = function () {
  this.obj = {}
  this.cacheList = []
}

Event.prototype.on = function (eventType, fn) {
  if (!this.obj[eventType]) {
    this.obj[eventType] = []
  }
  this.obj[eventType].push(fn)
  for (let i = 0; i < this.cacheList.length; i++) {
    // 订阅时,执行之前发布时,缓存下来的 cache
    this.cacheList[i]()
  }
}

Event.prototype.emit = function () {
  const arg = arguments
  const that = this
  function cache() {
    var eventType = Array.prototype.shift.call(arg)
    var arr = that.obj[eventType]
    for (let i = 0; i < arr.length; i++) {
      arr[i].apply(arr[i], arg)
    }
  }
  // 发布时,将 cache 缓存下来
  this.cacheList.push(cache)
}

const ob = new Event()
ob.emit('say', 'hello')
ob.on('say', function (msg) {
  console.log(msg) // hello
})

总结

发布订阅模式主要的好处就是对象之间的解耦,帮助我们写出更松耦合的代码。缺点是订阅者的创建是消耗一定的时间和内存的。使用过多也是难以维护的。