国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

javascript設(shè)計模式學(xué)習(xí)——觀察者模式

duan199226 / 2177人閱讀

摘要:最常見的觀察者模式事件監(jiān)聽器這是最簡單最普通的一種觀察者模式,除此以外還有等。動畫在動畫中廣泛使用了觀察者模式,動畫的開始完成暫停等,都需要觀察者來確定物體的行為和狀態(tài)。參考資料設(shè)計模式發(fā)布訂閱模式

Javascript活躍在事件驅(qū)動的環(huán)境中,比如鼠標(biāo)的響應(yīng)、事件的回調(diào)、網(wǎng)絡(luò)的請求等,觀察者模式又稱發(fā)布者-訂閱者(publisher-subscriber)模式,是處理對象及其行為和狀態(tài)之間的關(guān)系,管理人與任務(wù)之間的關(guān)系。

1. 最常見的觀察者模式
1.1 事件監(jiān)聽器
document.body.addEventListener("click", function () {
    console.log("you clicked me, poor guy!")
});

這是最簡單最普通的一種觀察者模式,除此click 以外還有loadblurdragfocusmouseover、等。事件監(jiān)聽器(listener)有別于事件處理器(handler),在事件監(jiān)聽器中,一個事件可以關(guān)聯(lián)多個監(jiān)聽器,每個監(jiān)聽器獨立處理監(jiān)聽到的消息;事件處理器是執(zhí)行處理事件發(fā)生后的關(guān)聯(lián)函數(shù),一種事件是能有一個處理函數(shù):

var dom = $(".dom");
var listener1 = function(e){
    //do one thing
}
var listener2 = function(e){
    //do another thing
}
addEvent(dom,"click",listener1);
addEvent(dom,"click",listener2);

在這個事件監(jiān)聽器的例子中,listener1listener2 都是dom元素的監(jiān)聽器,當(dāng)dom被點擊時,都會執(zhí)行各自的函數(shù);

var dom = document.getElementById("dom");
var handler1 = function(e){
    //do one thing
}
var handler2 = function(e){
    //do another thing
}
dom.onclick = handler1;
dom.onclick = handler2;

在這個事件處理器的例子中,handler1不會被執(zhí)行,只執(zhí)行handler2,是一次賦值的操作。

1.2 動畫

在動畫中廣泛使用了觀察者模式,動畫的開始、完成、暫停等,都需要觀察者來確定物體的行為和狀態(tài)。

//定義動畫
var Animation = function(){
    this.onStart = new Publisher;  //關(guān)于Publisher的設(shè)計將在1.3節(jié)介紹
    this.onComplete = new Publisher;
    this.onTween = new Publisher;
}
//定義一個原型方法
Animation.prototype.look = function(){
    this.onStart.deliver("animation started!");
    this.onTween.deliver("animation is going on!");
    this.onComplete.deliver("animation completed!");  
};

//實例一個box對象
var box = new Animation();

//定義三個函數(shù)作為subscribers
var openBox = function(msg){
    console.log(msg)
}
var checkBox = function(msg){
    console.log(msg)
}
var closeBox = function(msg){
    console.log(msg)
}

//訂閱事件
openBox.subscribe(box.onStart);
checkBox.subscribe(box.onTween);
closeBox.subscribe(box.onComplete);

//調(diào)用方法
box.look()

//animation started!
//animation is going on!
//animation completed!
1.3 觀察者的構(gòu)建

首先,需要一個發(fā)布者。先定義一個構(gòu)造函數(shù),為其定義一個數(shù)組,用以保存訂閱者信息:

function Publisher(){
    this.subscribes = [];
}

發(fā)布者具有發(fā)布消息的功能,定義一個deliver的原型函數(shù):

Publisher.prototype.deliver = function(data){
    this.subscribes.forEach(function(fn){
        fn(data);
    });
    return this;
}

接下來構(gòu)造訂閱方法:

Function.prototype.subscribe = function(publisher){
    var that = this;
    var alreadyExists = publisher.subscribes.some(function(el){
        return el === that;
    });
    if(!alreadyExists){
        publisher.subscribes.push(this);
    }
    return this;
}

直接在Function的prototype添加subscribe方法,這樣所有函數(shù)都可以調(diào)用該方法。這樣就構(gòu)建完畢了,使用方法參看1.2動畫的用例。
比較直觀的解釋(以onStart為例):當(dāng)box對象執(zhí)行look方法時,執(zhí)行onStart.deliver(),將onStart事件發(fā)布出去,廣播通知"animation started!",這個時候,一直在監(jiān)聽onStartopenBox監(jiān)聽到該事件發(fā)布的信息,打印出來。

1.4 另一種構(gòu)建觀察者的方式

這種方式模仿了nodejs的事件處理機制,代碼也比較簡潔:

    var scope = (function() {
    //消息列表
    var events = {};
    return {
        //訂閱消息
        on:function(name,hander){
            var index = 0;  //記錄消息時間的索引
            if(events[name]){  
                //消息名已存在,將處理函數(shù)放到該消息的事件隊列中
                index = events[name].push(hander) - 1; 
            }else{
                events[name] = [hander];
            }
            //返回當(dāng)前消息處理事件的移除函數(shù)
            return function(){
                events[name].splice(index,1);
            }
        },
        //關(guān)閉消息
        off:function(name){
            if(!events[name]) return;
            //消息存在,刪除消息
            delete events[name];
        },
        //消息發(fā)布
        emit:function(name,msg){
            //消息不存在,不處理
            if(!events[name]) return;
            //消息存在,將該事件處理隊列中每一個函數(shù)都執(zhí)行一次
            events[name].forEach(function(v,i){
                v(msg);
            });
        }
    }
})();

var sayHello = scope.on("greeting",function(msg){
    console.log("訂閱消息:" + msg);
});

var greeting = function(msg){
    console.log("發(fā)布消息:" + msg);
    scope.emit("greeting", msg);
}

greeting("hello Panfen!") 
1.5 nodejs中觀察者模式的實現(xiàn)方案

nodejs中有events模塊來實現(xiàn)觀察者模式,可參考Nodejs API-Events 談觀察者模式,大多數(shù)的模塊都集成了events模塊,所以可以直接使用emit發(fā)射事件和on監(jiān)聽事件,或者像下面這樣先定義一下;

var EventEmitter = require("events").EventEmitter;
var life = new EventEmitter();
life.setMaxListeners(11);       //設(shè)置最大監(jiān)聽數(shù),默認10

//發(fā)布和訂閱sendName
life.on("sendName",function(name){
    console.log("say hello to "+name);
});
life.emit("sendName","jeff");

//發(fā)布和訂閱sendName2
function sayBeautiful(name){
    console.log(name + " is beautiful");
}
life.on("sendName2",sayBeautiful);
life.emit("sendName2","jeff");

常用方法:

hasConfortListener :用于判斷發(fā)射的事件是否有監(jiān)聽器

removeListener :移除監(jiān)聽器

listenerCount :該事件所有監(jiān)聽器的總數(shù)

removeAllListeners :移除事件所有(或某個)的監(jiān)聽器

1.6 總結(jié)

觀察者模式建立了推送收聽的邏輯,適用于希望把人的行為和應(yīng)用程序的行為分開的場合。舉個例子來說:用戶點擊導(dǎo)航欄的一個tab時,會打開包含更多選項的子菜單,一般會選擇在知道哪個元素的情況下直接監(jiān)聽這個click事件,這樣做的弊端在于實現(xiàn)了與click事件直接綁在一起。更好的做法是:創(chuàng)建一個可觀察的onTabChange對象,關(guān)聯(lián)若干觀察者實現(xiàn)。

1.7 參考資料:

《Javascript設(shè)計模式》

發(fā)布(Publish)/ 訂閱(Subscribe)模式

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

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/88182.html

相關(guān)文章

  • javascript設(shè)計模式察者模式

    摘要:下面為學(xué)習(xí)筆記,對觀察者模式做簡單實現(xiàn)。注冊的事件被觸發(fā)后需要執(zhí)行的動作注冊事件及對應(yīng)的執(zhí)行動作觸發(fā)事件對比執(zhí)行事件前后的事件列表內(nèi)容觀察者模式在解決類的耦合中的應(yīng)用小例子。 這篇筆記主要記錄學(xué)習(xí)思路及收獲,分享出來拋磚引玉,如有謬誤或優(yōu)化空間,歡迎交流。 要理解觀察者模式,可以類比vue中的EventBus,其實就是一個全局的觀察者對象($bus),上面有注冊事件($bus.on()...

    Tamic 評論0 收藏0
  • 設(shè)計模式 -- 察者模式

    摘要:總結(jié)一下從表面上看觀察者模式里,只有兩個角色觀察者被觀察者而發(fā)布訂閱模式,卻不僅僅只有發(fā)布者和訂閱者兩個角色,還有第三個角色經(jīng)紀(jì)人存在。參考鏈接觀察者模式發(fā)布訂閱模式 做了這么長時間的 菜鳥程序員 ,我好像還沒有寫過一篇關(guān)于設(shè)計模式的博客...咳咳...意外,純屬意外。所以,我決定,從這一刻起,我要把設(shè)計模式在從頭學(xué)習(xí)一遍,不然都對不起我這 菜鳥 的身份。那這次,就從觀察者模式開始好啦...

    chengtao1633 評論0 收藏0
  • 設(shè)計模式 -- 察者模式

    摘要:總結(jié)一下從表面上看觀察者模式里,只有兩個角色觀察者被觀察者而發(fā)布訂閱模式,卻不僅僅只有發(fā)布者和訂閱者兩個角色,還有第三個角色經(jīng)紀(jì)人存在。參考鏈接觀察者模式發(fā)布訂閱模式 做了這么長時間的 菜鳥程序員 ,我好像還沒有寫過一篇關(guān)于設(shè)計模式的博客...咳咳...意外,純屬意外。所以,我決定,從這一刻起,我要把設(shè)計模式在從頭學(xué)習(xí)一遍,不然都對不起我這 菜鳥 的身份。那這次,就從觀察者模式開始好啦...

    makeFoxPlay 評論0 收藏0
  • JS程序

    摘要:設(shè)計模式是以面向?qū)ο缶幊虨榛A(chǔ)的,的面向?qū)ο缶幊毯蛡鹘y(tǒng)的的面向?qū)ο缶幊逃行┎顒e,這讓我一開始接觸的時候感到十分痛苦,但是這只能靠自己慢慢積累慢慢思考。想繼續(xù)了解設(shè)計模式必須要先搞懂面向?qū)ο缶幊蹋駝t只會讓你自己更痛苦。 JavaScript 中的構(gòu)造函數(shù) 學(xué)習(xí)總結(jié)。知識只有分享才有存在的意義。 是時候替換你的 for 循環(huán)大法了~ 《小分享》JavaScript中數(shù)組的那些迭代方法~ ...

    melody_lql 評論0 收藏0
  • 學(xué)習(xí)這些設(shè)計模式,讓你寫出更優(yōu)雅的代碼

    摘要:寫代碼容易,寫出優(yōu)雅的代碼難,寫易于維護的容易擴展的結(jié)構(gòu)清晰的代碼應(yīng)該是每位開發(fā)者努力的目標(biāo),而學(xué)習(xí)設(shè)計模式,合理的的使用能讓我們離這個目標(biāo)更進一步。 寫代碼容易,寫出優(yōu)雅的代碼難,寫易于維護的、容易擴展的、結(jié)構(gòu)清晰的代碼應(yīng)該是每位開發(fā)者努力的目標(biāo),而學(xué)習(xí)設(shè)計模式,合理的的使用能讓我們離這個目標(biāo)更進一步。最近看了《Javascript設(shè)計模式與開發(fā)實踐》這本書,一言以蔽之,真不錯的一本...

    songjz 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<