亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

JavaScript 觀察者模式

zhigoo / 2167人閱讀

摘要:生活中的觀察者模式就如我們?cè)趯Yu店預(yù)定商品如蘋果手機(jī),我們會(huì)向?qū)Yu店提交預(yù)定申請(qǐng),然后店家受申請(qǐng),正常這樣就完事了。中的觀察者模式在中觀察者模式的實(shí)現(xiàn)主要用事件模型。缺點(diǎn)使用全局的觀察者模式會(huì)明顯降低對(duì)象之間的聯(lián)系。

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

生活中的觀察者模式

就如我們?cè)趯Yu店預(yù)定商品(如:蘋果手機(jī)),我們會(huì)向?qū)Yu店提交預(yù)定申請(qǐng),然后店家受申請(qǐng),正常這樣就完事了。假如,近段時(shí)間蘋果手機(jī)的需求很大,而商品有限,那么商家就會(huì)要這些果粉預(yù)留電話等待通知,等到手機(jī)一到,商家就會(huì)遍歷果粉預(yù)留信息,然后發(fā)通知給這些果粉。生活中商家強(qiáng)調(diào)客戶在家等通知即可,并且說一有消息就會(huì)通知客戶,而不會(huì)傻到要客戶主動(dòng)打電話詢問,這樣不僅客戶的代價(jià)比較大,商家的負(fù)荷更大,用戶的輪詢方式也從打電話變成了查看短信息。

觀察者模式的優(yōu)勢(shì)

發(fā)布和訂閱這兩個(gè)對(duì)象是松耦合地聯(lián)系在一起的,它們不用彼此熟悉內(nèi)部的實(shí)現(xiàn)細(xì)節(jié),但這不影響它們之間的通信,它們只要知道彼此需要做什么就行。當(dāng)有新訂閱者增加時(shí),發(fā)布者不需要任何更改,同樣的當(dāng)發(fā)布者改變時(shí),訂閱者也不會(huì)受到影響。

就像新聞聯(lián)播一樣里面的央視主持人換了,也不影響我們看央視的新聞聯(lián)播,同樣你看或不看新聞聯(lián)播,對(duì)央視來說也無影響。

在異步通信中觀察者模式也是大有好處,發(fā)布者只需按順序的發(fā)布事件即可,而訂閱者只需在異步運(yùn)行期間訂閱相關(guān)事件即可。

JavaScript中的觀察者模式

在JavaScript中觀察者模式的實(shí)現(xiàn)主要用事件模型。

DOM事件
document.body.addEventListener("click", function() {
    console.log("hello world!");
});

相信這樣的代碼不少的同學(xué)都寫過,但我要說這其實(shí)就是一種觀察者模式的實(shí)現(xiàn),可能一些童鞋還不信,那么看一看修改后的代碼。

// 發(fā)布者
var pub = function() {
    console.log("歡迎訂閱!")
}
// 訂閱者
var sub = document.body;

// 訂閱者實(shí)現(xiàn)訂閱
sub.addEventListener("click", pub, false);

訂閱者可以任意的添加,發(fā)布者也可以隨意的修改。

自定義事件

雖然,使用dom事件可以輕松解決我們開發(fā)中的一部分問題;但是還有一些問題需要我們使用自定義事件來完成。
那面就說一說如何用自定義事件實(shí)現(xiàn)代理。

我們還以預(yù)定手機(jī)為例,參考dom事件的原理來實(shí)現(xiàn)觀察者模式,用用戶的電話號(hào)碼作為類型,用戶的定購(gòu)信息用一個(gè)回調(diào)函數(shù)來表示。

基本概念定義如下:

商家: 發(fā)布者

客戶: 訂閱者

緩存列表:記錄客戶的電話,方便商家遍歷發(fā)通知消息給客戶

注:緩存列表,我將它定義為一個(gè)對(duì)象,用戶的電話號(hào)碼作為key,用戶的預(yù)定信息是個(gè)數(shù)組作為value。

代碼實(shí)現(xiàn)如下:

// 定義商家
var merchants = {};
// 定義預(yù)定列表
merchants.orderList = {};
// 將增加的預(yù)訂者添加到預(yù)定客戶列表中
merchants.listen = function(id, info) {
    if(!this.orderList[id]) {
        this.orderList[id] = [];
    }
    this.orderList[id].push(info);
    console.log("預(yù)定成功")
};
//發(fā)布消息
merchants.publish = function() {
    var id = Array.prototype.shift.call(arguments);
    var infos = this.orderList[id];
    // 判斷是否有預(yù)訂信息
    if(!infos || infos.length === 0) {
        console.log("您還沒有預(yù)訂信息!");
        return false;
    }
    // 如果有預(yù)訂信息,則循環(huán)打印
    for (var i = 0, info; info = infos[i++];) {
        console.log("尊敬的客戶:");
        info.apply(this, arguments);
        console.log("已經(jīng)到貨了");
    }
};
// 定義一個(gè)預(yù)訂者customerA,并指定預(yù)定信息
var customerA = function() {
    console.log("黑色至尊版一臺(tái)");
};
// customerA 預(yù)定手機(jī),并留下預(yù)約電話
merchants.listen("15888888888", customerA); // 預(yù)定成功
// 商家發(fā)布通知信息
merchants.publish("15888888888");
/**
   尊敬的客戶:
   黑色至尊版一臺(tái)
   已經(jīng)到貨了
 */
取消訂閱

當(dāng)然,現(xiàn)實(shí)中我們可以預(yù)定,那么也可以取消預(yù)定。其實(shí)取消預(yù)定的方式也比較簡(jiǎn)單,就是將客戶從預(yù)定列表中清除出去。代碼實(shí)現(xiàn)如下:

merchants.remove = function(id, fn) {
    var infos = this.orderList[id];

    if(!infos) return false;

    if(!fn) {
        infos && (infos.length = 0);
    } else {
        for(var i = 0, len = infos.length; i < len; i++) {
            if(infos[i] === fn) {
                infos.splice(i, 1);
            }
        }
    }
};
merchants.remove("15888888888", customerA);
merchants.publish("15888888888"); // 您還沒有預(yù)訂信息!
全局的觀察者模式

實(shí)現(xiàn)的代碼結(jié)構(gòu)如下:

var observer = (function() {
    var orderList = {},
        listen,
        publish,
        remove;
    listen = function(id, fn) {
        ...
    };

    publish = function() {
        ...
    };

    remove = function(id, fn) {
        ...
    };

    return {
        listen: listen,
        publish: publish,
        remove: remove
    }
})();

優(yōu)點(diǎn):

使用了全局的觀察者模式后,我們不用管商家是誰(shuí),只要他能提供我們所需要的東西即可;而且我們也避免了為不同的商家都創(chuàng)建listen,publish,remove方法,這樣可以減少資源的浪費(fèi)。

缺點(diǎn):

使用全局的觀察者模式會(huì)明顯降低對(duì)象之間的聯(lián)系。一些方法將會(huì)被隱藏,而有時(shí)我們恰恰需要這些方法的暴露。

是先訂閱,還是先發(fā)布

在我被問到這個(gè)問題時(shí),我也是一愣,當(dāng)時(shí)腦袋里就冒出了‘你怎么不問是先有雞,還是先有蛋’這樣的想法。

按照我的理解我們實(shí)現(xiàn)觀察者模式,都是訂閱者先訂閱,然后接收發(fā)布者的通知消息。沒有反過來想,發(fā)布者先發(fā)布一條消息,然后等訂閱者接收,因?yàn)樵谖业南胂笾?,如果沒有訂閱者,這消息怎么成功發(fā)布。

后來有人跟我說有這樣的業(yè)務(wù)實(shí)現(xiàn),當(dāng)時(shí)我就不假思索的問什么業(yè)務(wù),他說QQ的離線模式。這種先發(fā)布后訂閱的形式是將信息先存儲(chǔ)起來,等到訂閱者訂閱,就立即將信息發(fā)送給訂閱者。如:當(dāng)我們將QQ調(diào)到離線模式,我們就無法接收信息;當(dāng)我們將QQ調(diào)到登錄模式,就馬上收在離線模式期間接收到的信息。

這樣的例子在生活中也有很多,還拿天氣預(yù)報(bào),它也可以理解為是先發(fā)布,我們后訂閱的模式。天預(yù)報(bào)信息會(huì)發(fā)布在網(wǎng)上,存儲(chǔ)在各個(gè)服務(wù)器上,我們需要時(shí)打開手機(jī)就可以得到。

注:提到觀察者模式我們就不得不說一下推模型和拉模型。推模型在事件發(fā)生時(shí),發(fā)布者會(huì)將變化狀態(tài)和數(shù)據(jù)都推送給訂閱者;拉模型在事件發(fā)生時(shí),發(fā)布者只會(huì)給訂閱者一個(gè)狀態(tài)改變通知,訂閱者會(huì)根據(jù)發(fā)布者提供的接口主動(dòng)拉取數(shù)據(jù)。

設(shè)計(jì)模式周周講

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/92831.html

相關(guān)文章

  • JavaScript 發(fā)布-訂閱模式

    摘要:發(fā)布訂閱模式訂閱者把自己想訂閱的事件注冊(cè)到調(diào)度中心,當(dāng)發(fā)布者發(fā)布該事件到調(diào)度中心,也就是該事件觸發(fā)時(shí),由調(diào)度中心統(tǒng)一調(diào)度訂閱者注冊(cè)到調(diào)度中心的處理代碼。 發(fā)布-訂閱模式,看似陌生,其實(shí)不然。工作中經(jīng)常會(huì)用到,例如 Node.js EventEmitter 中的 on 和 emit 方法;Vue 中的 $on 和 $emit 方法。他們都使用了發(fā)布-訂閱模式,讓開發(fā)變得更加高效方便。 一...

    13651657101 評(píng)論0 收藏0
  • JavaScript常用設(shè)計(jì)模式

    摘要:原文鏈接常用設(shè)計(jì)模式設(shè)計(jì)模式設(shè)計(jì)模式是一種在長(zhǎng)時(shí)間的經(jīng)驗(yàn)與錯(cuò)誤中總結(jié)出來可服用的解決方案。用來模擬接口的相關(guān)操作我很帥通過適配器函數(shù)來調(diào)用目的我很帥學(xué)習(xí)資料聽飛狐聊設(shè)計(jì)模式系列設(shè)計(jì)模式湯姆大叔 原文鏈接: JavaScript常用設(shè)計(jì)模式 設(shè)計(jì)模式 設(shè)計(jì)模式是一種在長(zhǎng)時(shí)間的經(jīng)驗(yàn)與錯(cuò)誤中總結(jié)出來可服用的解決方案。 設(shè)計(jì)模式主要分為3類: 創(chuàng)建型設(shè)計(jì)模式:專注于處理對(duì)象的創(chuàng)建 Const...

    RyanHoo 評(píng)論0 收藏0
  • JavaScript 設(shè)計(jì)模式(六):察者模式與發(fā)布訂閱模式

    摘要:觀察者模式維護(hù)單一事件對(duì)應(yīng)多個(gè)依賴該事件的對(duì)象關(guān)系發(fā)布訂閱維護(hù)多個(gè)事件主題及依賴各事件主題的對(duì)象之間的關(guān)系觀察者模式是目標(biāo)對(duì)象直接觸發(fā)通知全部通知,觀察對(duì)象被迫接收通知。 觀察者模式(Observer) 觀察者模式:定義了對(duì)象間一種一對(duì)多的依賴關(guān)系,當(dāng)目標(biāo)對(duì)象 Subject 的狀態(tài)發(fā)生改變時(shí),所有依賴它的對(duì)象 Observer 都會(huì)得到通知。 簡(jiǎn)單點(diǎn):女神有男朋友了,朋友圈曬個(gè)圖,甜...

    bingo 評(píng)論0 收藏0
  • Backbone精髓,察者模式和事件

    摘要:原文精髓,觀察者模式和事件交互邏輯更需要設(shè)計(jì)模式設(shè)計(jì)模式將人們?cè)谝酝拈_發(fā)過程中的經(jīng)驗(yàn)加以總結(jié),以指導(dǎo)后人。的事件根據(jù)上面討論,要實(shí)現(xiàn)觀察者模式,事件是非常重要的機(jī)制??偨Y(jié)雖然是模式的框架,但是其核心卻是界面的觀察者模式和事件機(jī)制。 前言 本人并非專業(yè)的前端,只是由于需要被迫轉(zhuǎn)做一段時(shí)間的前端,一段時(shí)間以來開始探索javascript上的MVC模式,最終打算從Backbone下手。在...

    Snailclimb 評(píng)論0 收藏0
  • JavaScript設(shè)計(jì)模式之發(fā)布-訂閱模式察者模式)-Part1

    摘要:設(shè)計(jì)模式與開發(fā)實(shí)踐讀書筆記。發(fā)布訂閱模式又叫觀察者模式,它定義了對(duì)象之間的一種一對(duì)多的依賴關(guān)系。附設(shè)計(jì)模式之發(fā)布訂閱模式觀察者模式數(shù)據(jù)結(jié)構(gòu)和算法系列棧隊(duì)列優(yōu)先隊(duì)列循環(huán)隊(duì)列設(shè)計(jì)模式系列設(shè)計(jì)模式之策略模式 《JavaScript設(shè)計(jì)模式與開發(fā)實(shí)踐》讀書筆記。 發(fā)布-訂閱模式又叫觀察者模式,它定義了對(duì)象之間的一種一對(duì)多的依賴關(guān)系。當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴它的對(duì)象都將得到通知。 例...

    muzhuyu 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<