JavaScript設(shè)計模式——觀察者模式

觀察者模式又被稱為發(fā)布-訂閱模式黍特,是設(shè)計模式中的一種行為型模式;

定義:

觀察者模式定義了一種一對多的對象依賴關(guān)系,當(dāng)被依賴的對象的狀態(tài)發(fā)生了改變摊崭,所有依賴它的對象都會得到通知坪圾;

白話解釋:

假如你去蘋果專賣店買最新款的iphone11晓折,因為iphone11剛出來不久,正處旺季兽泄,供貨不足漓概;當(dāng)你去專賣店的時候,店員告訴你暫時沒貨了病梢,但是你可以留下你的聯(lián)系方式胃珍,如果貨到了梁肿,會第一時間通知;當(dāng)然你肯定不會每天都去專賣店問iphone11到貨沒有觅彰,也不會天天給專賣店打電話吩蔑,因為你有你自己的工作和生活,不可能有那么多閑暇時間填抬;所以此時烛芬,店員讓你留下聯(lián)系方式,到貨了第一時間通知你飒责,不會給你帶來麻煩赘娄,而你只需要等著專賣店的電話即可;而這種方法就是一種典型的觀察者模式读拆;

首先我們還是來分析一下:

1.訂閱方法:我們把聯(lián)系方式給專賣店店員是屬于一種消息訂閱的消息擅憔,因為只有這樣你才能及時的知道iphone11到貨了,所有我們需要一個訂閱行為的具體方法檐晕;

2.預(yù)訂列表:要知道iphone11是屬于新版iphone暑诸,所以肯定不會是只有你一個人去預(yù)訂,所以店員為了方便統(tǒng)計還需要一個預(yù)訂列表來統(tǒng)計所有的預(yù)訂者的聯(lián)系方式以及預(yù)訂手機版本信息辟灰,所以我們這里先給它定義為一個對象个榕;key代表是預(yù)訂者的聯(lián)系方式,value代表預(yù)訂手機版本信息芥喇;

3.發(fā)布方法:當(dāng)iphone11到貨的時候西采,專賣店肯定要根據(jù)預(yù)訂列表來進行統(tǒng)一發(fā)布消息("iphone11到貨了,大家快來搶<炭亍P倒荨!")武通,所以專賣店需要一個發(fā)布方法來實行具體的發(fā)布行為霹崎;、

4.取消訂閱:萬物相對冶忱,能訂閱肯定就能取消訂閱尾菇;在等待iphone11到貨通知的時候,你急著用手機囚枪,所以直接買了華為的某款派诬,所以iphone11暫時對你來說需求不大,因為你已經(jīng)有了手機所以專賣店的iphone11是否到貨對你來說沒有任何意義了链沼;所以此時你不想被打擾默赂,需要取消訂閱消息;所以我們需要一個取消訂閱方法來實現(xiàn)具體的取消訂閱的行為括勺;

觀察者模式的應(yīng)用場景:

1缆八、DOM事件

如果你是一個前端開發(fā)人員谒臼,不管你讀這篇文章之前是否已經(jīng)了解觀察者模式,但是我能肯定你已經(jīng)用過觀察者模式耀里;

document.body.addEventListener('click', function() {
    console.log('hello world!');
});

這段代碼看著眼熟嗎?是的拾氓,這是一個DOM事件的監(jiān)聽冯挎;我們通過給body訂閱click事件(click相當(dāng)于上面的訂閱方法),因為瀏覽器并不知道你什么時候點擊鼠標(biāo)咙鞍,所以等你觸發(fā)click事件的時候才會觸發(fā)函數(shù)給你發(fā)布通知(發(fā)布方法)房官;DOM事件就是一個觀察者模式的實現(xiàn);

2续滋、vue雙向綁定v-model

我們作為前端開發(fā)人員翰守,肯定知道vue是一個MVVM模式的框架;vue的核心就是雙向綁定疲酌,那么雙向綁定的實現(xiàn)實際上就是一種觀察者模式蜡峰;因為你首先綁定了一個數(shù)據(jù)之后(訂閱方法),瀏覽器并不知道你什么時候修改朗恳,你頁面上所有綁定了該數(shù)據(jù)或者依賴該數(shù)據(jù)的節(jié)點其實就是一個預(yù)訂列表湿颅,只有等你修改了該數(shù)據(jù)的值的時候,vue才會通知(發(fā)布方法)到依賴該數(shù)據(jù)的方法/數(shù)據(jù)進行相應(yīng)的操作或刷新粥诫;

當(dāng)然觀察者模式絕不僅限于這倆種實現(xiàn)場景油航,在我們的生活中、業(yè)務(wù)場景中有很多觀察者模式的示例怀浆,之前我們第一篇工廠模式介紹設(shè)計模式的時候就說過了谊囚,設(shè)計模式是一種解決問題的思路而非一種固定的公式,那么我們怎么實現(xiàn)觀察者模式呢执赡?

觀察者模式的實現(xiàn):

    //定義商家
    var merchants = {};
    //定義預(yù)訂列表
    merchants.orderList = {};
    //將增加的預(yù)定者添加到預(yù)訂列表中   (訂閱方法)
    merchants.listen = function(id,info){
        //如果存在
        if(!this.orderList[id]){
            // (預(yù)訂列表)
            this.orderList[id] = [];
        }
        // 將用戶的預(yù)定的產(chǎn)品信息存入到數(shù)組中
        this.orderList[id].push(info);
    }
    //發(fā)布信息(發(fā)布方法)
    merchants.publish = function(){
        var id = Array.prototype.shift.call(arguments);
        var infos = this.orderList[id];
        if(!infos || infos.length === 0){
            console.log("您還沒有預(yù)定信息");
            return false;
        }

        for(var i = 0;i < infos.length;i++){
            console.log("預(yù)定成功");
            console.log("尊敬的用戶:")
            infos[i].apply(this,arguments);
            console.log("到貨了");
        }
    }
    //取消訂閱  
    merchants.remove = function(id,fn){
        var infos = this.orderList[id];
        if(!infos){ return false}

        if(!fn){
            console.log(123);
        }else{
            for(var i = 0;i < infos.length;i++){
                if(infos[i] === fn){
                    infos.splice(i,1);
                }
            }
        }
    }
    let customeA = function(){
        console.log("黑色尊享版一臺");
    }

    merchants.listen("15172103336",customeA);
    merchants.remove("15172103336",customeA);
    merchants.publish("15172103336");

上面的代碼稍微有點長镰踏,不過沒有很難;首先我們是定義了一個對象是作為商家搀玖,然后定義了一個空的對象作為預(yù)訂列表余境,再一步步的實現(xiàn)我們的訂閱方法和發(fā)布以及取消訂閱的方法;邏輯不復(fù)雜灌诅,但是有一些語法需要講解一下:

發(fā)布方法中的var id = Array.prototype.shift.call(arguments);這句的意思是將merchants.publish("15172103336");方法調(diào)用的時候第一個參數(shù)返回給它然后復(fù)制為id芳来,所以其實此時的id值為”15172103336“;

infos[i].apply(this,arguments);這個方法也不是特別好理解猜拾,首先infos里裝的是預(yù)訂者的手機號碼以及手機版本信息即舌,所以我們infos[i].apply(this,arguments);這個方法其實就是將"15172103336"對應(yīng)的手機版本信息函數(shù)進行調(diào)用了一遍;實際上等于infosi;

觀察者模式不管是在前端領(lǐng)域還是在現(xiàn)實生活中的應(yīng)用都是有很常見的場景挎袜,學(xué)好觀察者模式有利用我們學(xué)習(xí)vue的源碼知識顽聂,當(dāng)然不僅限于此肥惭,所以觀察者模式值得我們好好學(xué)習(xí),一句話:"你品紊搪,你細(xì)品蜜葱!" 今天付出的努力,在日后總會換成工資來回報你的耀石!哈哈哈

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末牵囤,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子滞伟,更是在濱河造成了極大的恐慌揭鳞,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件梆奈,死亡現(xiàn)場離奇詭異野崇,居然都是意外死亡,警方通過查閱死者的電腦和手機亩钟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門乓梨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人径荔,你說我怎么就攤上這事督禽。” “怎么了总处?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵狈惫,是天一觀的道長。 經(jīng)常有香客問我鹦马,道長胧谈,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任荸频,我火速辦了婚禮菱肖,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘旭从。我一直安慰自己稳强,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布和悦。 她就那樣靜靜地躺著退疫,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鸽素。 梳的紋絲不亂的頭發(fā)上褒繁,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天,我揣著相機與錄音馍忽,去河邊找鬼棒坏。 笑死燕差,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的坝冕。 我是一名探鬼主播徒探,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼喂窟!你這毒婦竟也來了刹帕?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤谎替,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后蹋辅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體钱贯,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年侦另,在試婚紗的時候發(fā)現(xiàn)自己被綠了秩命。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡褒傅,死狀恐怖弃锐,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布阳掐,位于F島的核電站认烁,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏膛虫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望饶碘。 院中可真熱鬧,春花似錦馒吴、人聲如沸扎运。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽豪治。三九已至,卻和暖如春莹捡,著一層夾襖步出監(jiān)牢的瞬間鬼吵,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工篮赢, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留齿椅,地道東北人琉挖。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像涣脚,于是被迫代替她去往敵國和親示辈。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容