JS發布-訂閱模式

發布-訂閱模式廣泛應用于異步編程中,這是一種替代傳遞回調函數的方案。

現實中的例子:

??????小明想買房,到了售樓處被告知,該樓盤的房子早已售罄。售樓MM告訴小明,不久后還有一些尾盤推出,時間還未定。
??????小明記下了售樓處的電話,以后每天都會打電話詢問是否可購買。除了小明,還有小紅、小強也會每天向售樓處咨詢這個問題。可能售樓處每天回答 1000個相同內容的電話。
當然現實中銷售公司會一一將客戶的電話記錄下來,新樓盤推出的時候,售樓 MM會翻開花名冊,遍歷上面的電話號碼,依次發送一條短信來通知他們。

發布 - 訂閱模式的作用

??????購房者不用再天天給售樓處打電話咨詢開售時間,在合適的時間點,售樓處作為發布者會通知這些消息訂閱者
??????購房者和售樓處之間不再強耦合在一起,當有新的購房者出現時,他只需把手機號碼留在售樓處,售樓處不關心購房者的任何情況。 而售樓處的變動也不會影響購買者,比如售樓 MM 離職,這些改變都跟購房者無關,只要售樓處記得發短信這件事情。

發布訂閱模式可以取代對象之間硬編碼的通知機制,一個對象不用再顯式地調用另一個對象的某個接口,讓兩個對象低耦合地聯系在一起。
其實只要我們曾經在DOM上綁定過事件,就已經用過此模式:

document.body.addEventListener('click', () => {
    alert('hello world')
})
document.body.click()
以下用發布-訂閱模式,寫以下購房者與售樓處的故事
let event = {
    clientList: {},
    listen (key, fn) {
        if (!this.clientList[key]) {
            this.clientList[key] = []
        }
        this.clientList[key].push(fn)   // 訂閱的消息添加進緩存列表
    },
    trigger (type, money) {
        let fns = this.clientList[type]
        if (!fns || fns.length === 0) { // 如果沒有綁定對應的消息
            return false
        }
        fns.forEach(fn => {
            fn.apply(this, [money])
        })
    }
}

// 再定義一個installEvent函數,用于給所有對象動態安裝發布-訂閱功能
// 如:另一家售樓處也想要這個功能,就可以調用這個注冊了,不同再寫多一次這段代碼
let installEvent = obj => {
    for (let i in event) {
        obj[i] = event[i]
    }
}

// 給售樓處對象salesOffices動態增加發布-訂閱功能
let salesOffices = {}
installEvent(salesOffices)
// 小明訂閱信息
salesOffices.listen('squareMeter88', price => {
    console.log('小明,你看中的88平方的房子,價格=' + price)
})
// 小光訂閱信息
salesOffices.listen('squareMeter88', price => {
    console.log('小光,你看中的88平方的房子,價格=' + price)
})
// 小紅訂閱信息
salesOffices.listen('squareMeter100', price => {
    console.log('小紅,你看中的100平方的房子,價格=' + price)
})
salesOffices.trigger('squareMeter88', 2000000)
salesOffices.trigger('squareMeter100', 2500000)

運行結果:

小明,你看中的88平方的房子,價格=2000000
小光,你看中的88平方的房子,價格=2000000
小紅,你看中的100平方的房子,價格=2500000

總結

??????發布 — 訂閱模式的優點非常明顯,一為時間上的解耦,二為對象之間的解耦。它的應用非常廣泛,既可以用在異步編程中,也可以幫助我們完成更松耦合的代碼編寫。發布 — 訂閱模式還可以用來幫助實現一些別的設計模式,比如中介者模式。 從架構上來看,無論是 MVC還是 MVVM,都少不了發布 — 訂閱模式的參與,而且JavaScript本身也是一門基于事件驅動的語言。

缺點

??????當然,發布 — 訂閱模式也不是完全沒有缺點。創建訂閱者本身要消耗一定的時間和內存,而且當你訂閱一個消息后,也許此消息最后都未發生,但這個訂閱者會始終存在于內存中。另外,發布 — 訂閱模式雖然可以弱化對象之間的聯系,但如果過度使用的話,對象和對象之間的必要聯系也將被深埋在背后,會導致程序難以跟蹤維護和理解。特別是有多個發布者和訂閱者嵌套到一起的時候,要跟蹤一個 bug不是件輕松的事情。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • JavaScript設計模式六(發布-訂閱模式) 發布-訂閱模式又叫做觀察者模式,定義: 定義對象間的一種一對多的...
    moyi_gg閱讀 459評論 0 0
  • 工廠模式類似于現實生活中的工廠可以產生大量相似的商品,去做同樣的事情,實現同樣的效果;這時候需要使用工廠模式。簡單...
    舟漁行舟閱讀 7,827評論 2 17
  • 本節主講: 1:什么是spring boot?它哪些特點以至于我們去學習它? 2:使用spring boot 寫出...
    凱哥Java閱讀 602評論 0 3
  • 假設的情形是縮放的時候,例如點擊屏幕上的一個點進行縮放,縮放后的點相對于手指或者說屏幕的位置是不變的。 下面的例子...
    stone_yao閱讀 882評論 0 0
  • 如夢令 錦瑟涼春禪境,街市燈如晝應。 便對酒當歌,月照窗欞傾景。 疏影,疏影,醉后大夢晨方醒。
    沐宸ANTONIA閱讀 410評論 0 2