學習設計模式——發佈-訂閱模式

發佈訂閱模式,又叫觀察者模式,它定義了一種一對多的關係,讓多個訂閱者對象監聽某一個發佈者,發佈者狀態發生更新時派發信息給每一個訂閱者。
舉個例子,我想買一雙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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章