【設(shè)計(jì)模式】發(fā)布-訂閱模式

發(fā)布-訂閱模式又叫觀察者模式,它定義對象間的一種一對多的依賴關(guān)系,當(dāng)一個(gè)對象的狀態(tài)發(fā)生改變的時(shí)候,所有依賴于它的對象都將得到通知。

舉個(gè)栗子

比如售樓中心,因?yàn)榉吭淳o張,小紅、小明、老王每天都要打電話到售樓前臺詢問今天是否有新樓盤,這樣售樓前臺每天就需要接收很大量的咨詢。
發(fā)布-訂閱模式就是,售樓前臺MM將每個(gè)人的電話都記錄下來,當(dāng)有新樓盤的時(shí)候,就遍歷一遍這些電話號碼,依次打電話通知。其中售樓前臺是發(fā)布者,小紅、小明、老王是訂閱者。
優(yōu)點(diǎn):

  • 在合適的時(shí)間發(fā)布者會通知訂閱者。這說明發(fā)布-訂閱模式可以廣泛應(yīng)用于異步編程中,可以替代回掉函數(shù)的方式,無需過多關(guān)心異步運(yùn)行期間的內(nèi)部狀態(tài),只需要訂閱感興趣的事件發(fā)生點(diǎn)。
  • 減少發(fā)布者和訂閱者之間的耦合,發(fā)布者只記錄一個(gè)訂閱者的電話,并不關(guān)心訂閱者是女人還是猴子。這個(gè)優(yōu)點(diǎn)說明可以訂閱-發(fā)布模式可以取代對象之間硬編碼的通知機(jī)制,不需要再顯式的調(diào)用另一個(gè)對象的某個(gè)接口,這讓對象之間松耦合的聯(lián)系在一起,當(dāng)新訂閱者出現(xiàn)的時(shí)候,發(fā)布者代碼不需要作任何修改,同理,當(dāng)發(fā)布者需求改變時(shí)也不會影響到之前的訂閱者。
發(fā)布訂閱模式.png

典型應(yīng)用場景

  • 時(shí)間解耦:應(yīng)用于異步編程
  • 對象解耦:接口之間調(diào)用不再顯示的進(jìn)行

發(fā)布-訂閱模式通用實(shí)現(xiàn)

var event = {
    clientList: [], //緩存列表,存放訂閱者的回掉函數(shù)
    // 增加訂閱者
    addListen: function (key, fn) { // key是訂閱的消息類型,fn是回調(diào)函數(shù)
        if (!this.clientList[key]) {
            this.clientList[key] = []; // 如果還沒有訂閱過此類消息,給該類消息創(chuàng)建一個(gè)緩存列表
        }
        this.clientList[key].push(fn); // 訂閱的消息添加進(jìn)消息緩存列表
    },
    // 發(fā)布消息
    emit: function () { 
        var key = Array.prototype.shift.call(arguments),  // 取出消息類型
            fns = this.clientList[key]; // 取出該類型的消息對應(yīng)的回調(diào)函數(shù)組成的數(shù)組
        if(!fns || fns.length === 0) {
            return false;
        }

        for (var i=0,fn; fn = fns[i++]) {
            fn.apply(this, arguments); //arguments是發(fā)布消息時(shí)附送的參數(shù)
        }
    }
}

再定義一個(gè) installEvent 函數(shù),這個(gè)函數(shù)可以給所有的對象都動態(tài)安裝發(fā)布—訂閱功能:

var installEvent = function( obj ){ for ( var i in event ){ 給obj對象安裝發(fā)布-定義模式
    obj[ i ] = event[ i ]; }
};

給售樓處對象增加發(fā)布-訂閱功能:

var salesOffice = {};
installEvent(salesOffice); // 添加訂閱-發(fā)布完畢

// 對象小明訂閱消息
salesOffice.addListen('square88', function(price) {
    console.log( '價(jià)格= ' + price );// 回調(diào)函數(shù)
});

// 對象小紅訂閱消息
salesOffice.addListen('square100', function(price) {
    console.log( '價(jià)格= ' + price );// 回調(diào)函數(shù)
});

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

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

  • 又叫做觀察者模式,定義對象之中一種一對多的依賴關(guān)系,當(dāng)一個(gè)對象的狀態(tài)發(fā)生改變時(shí)候,所有依賴于它的對象都將得到通知。...
    壽_司閱讀 3,904評論 0 1
  • javascript設(shè)計(jì)模式與開發(fā)實(shí)踐 設(shè)計(jì)模式 每個(gè)設(shè)計(jì)模式我們需要從三點(diǎn)問題入手: 定義 作用 用法與實(shí)現(xiàn) 單...
    穿牛仔褲的蚊子閱讀 4,494評論 0 13
  • 發(fā)布-訂閱模式廣泛應(yīng)用于異步編程中,這是一種替代傳遞回調(diào)函數(shù)的方案。 現(xiàn)實(shí)中的例子: 小明想買房,到了售樓處被告知...
    ThomasCho閱讀 8,012評論 1 8
  • 工廠模式類似于現(xiàn)實(shí)生活中的工廠可以產(chǎn)生大量相似的商品,去做同樣的事情,實(shí)現(xiàn)同樣的效果;這時(shí)候需要使用工廠模式。簡單...
    舟漁行舟閱讀 8,131評論 2 17
  • “明天你是否會想起,昨天你寫的日記。 明天你是否會掂記,曾經(jīng)最愛哭的你。 ………” 同學(xué)們,一生當(dāng)中,你們經(jīng)歷過了...
    狩望_佛山閱讀 578評論 4 10

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