设计模式学习(二):发布-订阅模式

什么是发布-订阅模式

发布-订阅模式又叫观察者模式,它定义对象间的一对多的依赖关系,当一个对象的状态发生变化时,所有订阅它的对象都将得到通知;实现发布-订阅模式有以下几步:

  • 首先要指定好谁充当发布者;
  • 然后给发布者添加一个缓存列表,用于存放回调函数以便通知订阅者;
  • 最后发布消息的时候,发布者会遍历这个缓存列表,依次触发里面存放的订阅者回调函数。

代码实现

// event.js
let event = {
  clientObj: {},
  /**
   * @param {string} key
   * @param {function} fn
  */
  subscribe: function (key, fn) {
    if (!this.clientObj[key]) {
      this.clientObj[key] = []
    }
    this.clientObj[key].push(fn)
  },
  publish: function () {
    let key = Array.prototype.shift.call(arguments)
    let fns = this.clientObj[key]
    if (!fns || !fns.length) {
      return false
    }
    fns.forEach(fn => {
      fn.apply(this, arguments)
    })
  },
  /** @param {string} key */
  unSubscribe (key) {
    this.clientObj[key] = []
  },
  unSubscribeAll () {
    this.clientObj = {}
  },
}
/**
 * @describe 维护一个方法,为对象安装发布-订阅功能
*/
export const EventMitt = function (obj) {
  for (let key in event) {
    obj[key] = event[key]
  }
}


// 使用,index.js
import { EventMitt } from './event.js'
let event = {}
EventMitt(event)
event.subscribe('flag1', (val) => {
  console.log(val) // test1
})
event.subscribe('flag2', (val) => {
  console.log(val) // test2
})
event.publish('flag1', 'test1')
event.publish('flag2', 'test2')

用ES6来重写这个发布-订阅模式

// event.js
export class EventMitt {
  /** @private */
  constructor () {
    this.clientObj = {}
  }

  publish () {
    let key = Array.prototype.shift.call(arguments)
    let fns = this.clientObj[key]
    if (!fns || !fns.length) {
      return false
    }
    fns.forEach(fn => {
      fn.apply(this, arguments)
    })
  }

  /**
   * @param {string} key
   * @param {function} fn
  */
  subscribe (key, fn) {
    if (!this.clientObj[key]) {
      this.clientObj[key] = []
    }
    this.clientObj[key].push(fn)
  }

  /** @param {string} key */
  unSubscribe (key) {
    this.clientObj[key] = []
  }

  unSubscribeAll () {
    this.clientObj = {}
  }
}

// 使用,index.js
import { EventMitt } from './event.js'
const eventMitt = new EventMitt()

eventMitt.subscribe('flag1', (val) => {
  console.log(val) // test1
})
eventMitt.subscribe('flag2', (val) => {
  console.log(val) // test2
})
eventMitt.publish('flag1', 'test1')
eventMitt.publish('flag2', 'test2')

参考:
《JavaScript设计模式与实践开发》

posted @ 2021-12-03 15:07  coderInside  阅读(85)  评论(0)    收藏  举报