發(fā)布訂閱模式

生活中的發(fā)布訂閱

淘寶賣家屬于發(fā)布者。顧客小紅等一群吃瓜群眾是訂閱者。群眾訂閱淘寶賣家的店鋪,賣家有新消息就會(huì)通知所有人。

發(fā)布訂閱模式的優(yōu)點(diǎn)

  1. 支持簡(jiǎn)單的廣播通信,當(dāng)對(duì)象狀態(tài)發(fā)生改變時(shí),會(huì)自動(dòng)通知已經(jīng)訂閱過(guò)的對(duì)象。
    比如上面的列子,小明,小紅不需要天天逛淘寶網(wǎng)看鞋子到了沒(méi)有,在合適的時(shí)間點(diǎn),發(fā)布者(賣家)來(lái)貨了的時(shí)候,會(huì)通知該訂閱者(小紅,小明等人)。

  2. 發(fā)布者與訂閱者耦合性降低,發(fā)布者只管發(fā)布一條消息出去,它不關(guān)心這條消息如何被訂閱者使用,同時(shí),訂閱者只監(jiān)聽(tīng)發(fā)布者的事件名,只要發(fā)布者的事件名不變,它不管發(fā)布者如何改變;同理賣家(發(fā)布者)它只需要將鞋子來(lái)貨的這件事告訴訂閱者(買家),他不管買家到底買還是不買,還是買其他賣家的。只要鞋子到貨了就通知訂閱者即可。

簡(jiǎn)易版發(fā)布訂閱代碼

const shoeObj = {};// 定義發(fā)布者
shoeObj.list = {};// 緩存列表 存放訂閱者回調(diào)函數(shù)
// 增加訂閱者
shoeObj.listen = function listen(key, fn) {
  if (Array.isArray(shoeObj.list[key])) {
    shoeObj.list[key].push(fn);
  } else {
    shoeObj.list[key] = [fn];
  }
};
// 發(fā)布消息
shoeObj.trigger = function trigger() {
  const key = Array.prototype.shift.call(arguments); // 取出消息類型名稱
  const fns = this.list[key];  // 取出該消息對(duì)應(yīng)的回調(diào)函數(shù)的集合
// 如果沒(méi)有訂閱過(guò)該消息的話,則返回
    if(!fns || fns.length === 0) {
        return;
    }
    for(var i = 0,fn; fn = fns[i++]; ) {
        fn.apply(this,arguments); // arguments 是發(fā)布消息時(shí)附送的參數(shù)
    }
};
// 小紅訂閱如下消息
shoeObj.listen('red',function(size){
    console.log("尺碼是:"+size);  
});

// 小花訂閱如下消息
shoeObj.listen('block',function(size){
    console.log("再次打印尺碼是:"+size); 
});
shoeObj.trigger("red",40);
shoeObj.trigger("block",42);

代碼封裝

我們知道,對(duì)于上面的代碼,小紅去買鞋這么一個(gè)對(duì)象shoeObj 進(jìn)行訂閱,但是如果以后我們需要對(duì)買房子或者其他的對(duì)象進(jìn)行訂閱呢,我們需要復(fù)制上面的代碼,再重新改下里面的對(duì)象代碼;為此我們需要進(jìn)行代碼封裝;

const event = {
  list: {},
  listen:  function listen(key, fn) {
    if (Array.isArray(this.list[key])) {
      this.list[key].push(fn);
    } else {
      this.list[key] = [fn];
    }
  };
  trigger: function trigger() {
    const key = Array.prototype.shift.call(arguments); // 取出消息類型名稱
    const fns = this.list[key];  // 取出該消息對(duì)應(yīng)的回調(diào)函數(shù)的集合
  // 如果沒(méi)有訂閱過(guò)該消息的話,則返回
    if(!fns || fns.length === 0) {
        return;
    }
    for(var i = 0,fn; fn = fns[i++]; ) {
        fn.apply(this,arguments); // arguments 是發(fā)布消息時(shí)附送的參數(shù)
    }
  };
  
};

我們?cè)诙x一個(gè)initEvent函數(shù),這個(gè)函數(shù)使所有的普通對(duì)象都具有發(fā)布訂閱功能,如下代碼:

var initEvent = function(obj) {
    for(var i in event) {
        obj[i] = event[i];
    }
};

取消訂閱
event.cancel = function(key, fn){
 //     如果存在該類型的消息
      if(event.list[key] instanceof Array){
          var i = event.list[type].length -1;
  // 遍歷通知方法
          for(; i >= 0 ; i--){
  //     如果有通知該訂閱者的方法,則移除
  //     &&的短路機(jī)制
 //     splice的三種功能(刪除、替換、插入)之一
           event.list[type][i] === fn && event.list[type].splice(i,1);
           }
     }
}

Javascript中理解發(fā)布--訂閱模式

觀察者模式跟發(fā)布訂閱模式1
觀察者模式跟發(fā)布訂閱模式2
這篇文章我說(shuō)的 其實(shí)是觀察者模式。
在觀察者模式中,觀察者需要直接訂閱目標(biāo)事件;在目標(biāo)發(fā)出內(nèi)容改變的事件后,直接接收事件并作出響應(yīng)
在發(fā)布訂閱模式中,發(fā)布者和訂閱者之間多了一個(gè)發(fā)布通道;一方面從發(fā)布者接收事件,另一方面向訂閱者發(fā)布事件;訂閱者需要從事件通道訂閱事件

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 工廠模式類似于現(xiàn)實(shí)生活中的工廠可以產(chǎn)生大量相似的商品,去做同樣的事情,實(shí)現(xiàn)同樣的效果;這時(shí)候需要使用工廠模式。簡(jiǎn)單...
    舟漁行舟閱讀 8,140評(píng)論 2 17
  • 發(fā)布訂閱模式 發(fā)布/訂閱模式又叫觀察者模式,它定義對(duì)象間的一種一對(duì)多的依賴關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依...
    自度君閱讀 2,112評(píng)論 0 2
  • 發(fā)布/訂閱模式又叫觀察者模式,它定義對(duì)象間的一種一對(duì)多的依賴關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對(duì)象都...
    風(fēng)銘閱讀 2,812評(píng)論 0 1
  • 日子還是要繼續(xù)的。每次出操的時(shí)候,我們老師會(huì)檢查我們女生的頭發(fā),那個(gè)時(shí)候?qū)W校有好多女同學(xué)都染了虱子,學(xué)校要求老師一...
    什么樣的幸福閱讀 226評(píng)論 0 0
  • 朋友圈中一個(gè)非常不可思議的故事:鄰居表姐的老公非常愛(ài)喝酒,經(jīng)常喝得醉醺醺回家,其實(shí)性質(zhì)已經(jīng)類似於酗酒了。 有一次,...
    好彩妹閱讀 288評(píng)論 0 0

友情鏈接更多精彩內(nèi)容