JS設(shè)計(jì)模式七:發(fā)布-訂閱模式

發(fā)布-訂閱模式簡(jiǎn)述

發(fā)布---訂閱模式又叫觀察者模式,它定義了對(duì)象間的一種一對(duì)多的關(guān)系,讓多個(gè)觀察者對(duì)象同時(shí)監(jiān)聽某一個(gè)主題對(duì)象,當(dāng)一個(gè)對(duì)象發(fā)生改變時(shí),所有依賴于它的對(duì)象都將得到通知。

以網(wǎng)購(gòu)為例:

假設(shè)小紅看上了一雙鞋子,但該鞋子已經(jīng)斷貨了,賣家承諾她到貨通知。與此同時(shí),小明、小花燈也關(guān)注了這雙鞋子。

在這個(gè)場(chǎng)景中,賣家就是發(fā)布者,小紅等人都屬于訂閱者。當(dāng)鞋子到貨時(shí),會(huì)依次通知到每個(gè)人。

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

  1. 支持簡(jiǎn)單的廣播通信,當(dāng)對(duì)象狀態(tài)發(fā)生改變時(shí),會(huì)自動(dòng)通知已經(jīng)訂閱過(guò)的對(duì)象。
  2. 發(fā)布者與訂閱者耦合性降低,發(fā)布者只管發(fā)布一條消息出去,它不關(guān)心這條消息如何被訂閱者使用,同時(shí),訂閱者只監(jiān)聽發(fā)布者的事件名,只要發(fā)布者的事件名不變,它不管發(fā)布者如何改變;同理賣家(發(fā)布者)它只需要將鞋子來(lái)貨的這件事告訴訂閱者(買家),他不管買家到底買還是不買,還是買其他賣家的。只要鞋子到貨了就通知訂閱者即可。

發(fā)布訂閱模式的缺點(diǎn):

創(chuàng)建訂閱者需要消耗一定的時(shí)間和內(nèi)存。如果過(guò)度使用的話,反而使代碼不好理解及代碼不好維護(hù)等等。

如何實(shí)現(xiàn)發(fā)布訂閱模式?

  1. 首先要想好誰(shuí)是發(fā)布者(比如上面的賣家)。
  2. 然后給發(fā)布者添加一個(gè)緩存列表,用于存放回調(diào)函數(shù)來(lái)通知訂閱者(比如上面的買家收藏了賣家的店鋪,賣家通過(guò)收藏了該店鋪的一個(gè)列表名單)。
  3. 最后就是發(fā)布消息,發(fā)布者遍歷這個(gè)緩存列表,依次觸發(fā)里面存放的訂閱者回調(diào)函數(shù)。

實(shí)戰(zhàn)

發(fā)布訂閱模式是最經(jīng)典的設(shè)計(jì)模式之一,介紹的文章也非常多。這里不打算過(guò)多介紹。直接上代碼~~~

var Event = (function(){
    var list = {},
          listen,
          trigger,
          remove;
          listen = function(key,fn){
            if(!list[key]) {
                // 如果還沒有訂閱過(guò)此類消息,給該類消息創(chuàng)建一個(gè)緩存列表
                list[key] = [];
            }
            list[key].push(fn); // 訂閱消息添加到緩存列表
        };
        trigger = function(){
            var key = Array.prototype.shift.call(arguments), // 取出消息類型名稱
                 fns = list[key]; // 取出該消息對(duì)應(yīng)的回調(diào)函數(shù)的集合
            // 如果沒有訂閱過(guò)該消息的話,則返回
            if(!fns || fns.length === 0) {
                return false;
            }
            for(var i = 0, fn; fn = fns[i++];) {
                fn.apply(this,arguments); // arguments 是發(fā)布消息時(shí)附送的參數(shù)
            }
        };
        remove = function(key,fn){
            // 如果key對(duì)應(yīng)的消息沒有訂閱過(guò)的話,則返回
            var fns = list[key];
            // 如果沒有傳入具體的回調(diào)函數(shù),表示需要取消key對(duì)應(yīng)消息的所有訂閱
            if(!fns) {
                return false;
            }
            if(!fn) {
                fns && (fns.length = 0);
            }else {
                for(var i = fns.length - 1; i >= 0; i--){
                    var _fn = fns[i];
                    if(_fn === fn) {
                        fns.splice(i,1);// 刪除訂閱者的回調(diào)函數(shù)
                    }
                }
            }
        };
        return {
            listen: listen,
            trigger: trigger,
            remove: remove
        }
})();
// 測(cè)試代碼如下:
Event.listen("color",function(size) {
    console.log("尺碼為:"+size); // 打印出尺碼為42
});
Event.trigger("color",42);
?著作權(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,131評(píng)論 2 17
  • 1.發(fā)布訂閱模式介紹 發(fā)布---訂閱模式又叫觀察者模式,它定義了對(duì)象間的一種一對(duì)多的關(guān)系,讓多個(gè)觀察者對(duì)象同時(shí)監(jiān)聽...
    JSUED閱讀 851評(píng)論 1 4
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,234評(píng)論 25 708
  • 騎著車,在路上,很輕松,一點(diǎn)兒也不費(fèi)力,風(fēng)在耳邊喝,太陽(yáng)就這么斜著射來(lái),很愜意,心情很美麗。 猛然間,驚醒,哎,不...
    南木的小屋閱讀 398評(píng)論 5 2
  • 當(dāng)一般人追求學(xué)而優(yōu)則仕的時(shí)候,莊子選擇無(wú)用。這個(gè)無(wú)用我認(rèn)為和“塞翁失馬,焉知非福”的意思,形體無(wú)用可以不必服兵役和...
    愛同哥的奧利奧閱讀 277評(píng)論 0 0

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