学习设计模式——发布-订阅模式

发布订阅模式,又叫观察者模式,它定义了一种一对多的关系,让多个订阅者对象监听某一个发布者,发布者状态发生更新时派发信息给每一个订阅者。
举个例子,我想买一双AJ鞋,鞋店没货了,我给店员留个号码,我不关心店家什么时候到货。店家到货后店员会给我打电话通知我,我想要的鞋到货了,我可以去购买。

代码实现

// ES5 IIFE 实现
    var Publisher = (function() {
      var _subsMap = {} // 存储订阅者
      return {
        // 消息订阅
        subscribe(type, cb) {
          if(_subsMap[type]) {
            if(_subsMap[type].indexOf(cb) === -1) {
              _subsMap[type].push(cb)
            }
          } else {
            _subsMap[type] = [cb]
          }
        },
        // 消息退订
        unSubscribe(type, cb) {
          if(!_subsMap[type] || _subsMap[type].indexOf(cb) === -1) return
          var idx = _subsMap[type].indexOf(cb)
          _subsMap[type].splice(idx, 1)
        },
        // 消息发布
        notify(type) {
          if(!_subsMap[type]) return
          var params = Array.prototype.slice.call(arguments)
          _subsMap[type].forEach(function(cb) {
            cb(params)
          })
        }
      }
    })()

    function piXie(message) {
      console.log('pipipi'+message)
    }
    Publisher.subscribe('运动鞋', message => console.log('AJ830'+message)) // 订阅运动鞋
    Publisher.subscribe('运动鞋', message => console.log('JK960'+message)) // 订阅运动鞋
    Publisher.subscribe('皮鞋', piXie) // 订阅皮鞋

    Publisher.notify('运动鞋', '运动鞋到货~速来')
    Publisher.notify('皮鞋', '皮鞋到货~速来')
    Publisher.unSubscribe('皮鞋', piXie)
    Publisher.notify('皮鞋', '皮鞋到货~速来2')

    // ES6
    class Publisher2 {
      constructor() {
        this._subsMap = {}
      }

      subscribe(type, cb){
        if(this._subsMap[type]) {
          if(!this._subsMap[type].includes(cb)) {
            this._subsMap[type].push(cb)
          }
        } else {
          this._subsMap[type] = [cb]
        }
      }

      unSubscribe(type, cb) {
        if(!this._subsMap[type] || !this._subsMap[type].includes(cb)) return
        const idx = this._subsMap[type].indexOf(cb)
        this._subsMap[type].splice(idx, 1)
      }

      notify(type, ...payload) {
        if(!this._subsMap[type]) return
        this._subsMap[type].forEach(cb => cb(...payload))
      }
    }

    const adadis = new Publisher2()
    function fanBuXie(message) {
      console.log('139zzz'+ message)
    }
    adadis.subscribe('运动鞋', message => console.log('152xxx'+ message))// 订阅运动鞋
    adadis.subscribe('运动鞋', message => console.log('138yyy'+ message))
    adadis.subscribe('帆布鞋', fanBuXie)// 订阅帆布鞋
    adadis.notify('运动鞋',' 运动鞋到货了 ~') // 打电话通知买家运动鞋消息
    adadis.unSubscribe('帆布鞋', fanBuXie) //取消订阅帆布鞋信息
    adadis.notify('帆布鞋',' 帆布鞋售罄了 T.T') // 打电话通知买家帆布鞋消息
    ;

发布-订阅模式的通用实现

  1. Publisher:发布者,当消息发生时负责通知对应订阅者
  2. Subscriber:订阅者,当消息发生时被通知的对象
  3. SubscriberMap:持有不同 type 的数组,存储有所有订阅者的数组
  4. type:消息类型,订阅者可以订阅的不同消息类型
  5. subscribe:该方法为将订阅者添加到 SubscriberMap 中对应的数组中
  6. unSubscribe:该方法为在 SubscriberMap 中删除订阅者
  7. notify:该方法遍历通知 SubscriberMap 中对应 type 的每个订阅者
发布了163 篇原创文章 · 获赞 99 · 访问量 69万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章