首頁 >web前端 >js教程 >JavaScript設計模式之觀察者模式(發佈者-訂閱者模式)_javascript技巧

JavaScript設計模式之觀察者模式(發佈者-訂閱者模式)_javascript技巧

WBOY
WBOY原創
2016-05-16 16:35:421110瀏覽

觀察者模式( 又叫發布者-訂閱者模式)應該是最常用的模式之一. 在很多語言裡都得到大量應用. 包括我們平時接觸的dom事件. 也是js和dom之間實現的一種觀察者模式.

複製程式碼 程式碼如下:

div.onclick  =  function click (){
alert ( ”click' )
}

只要訂閱了div的click事件. 當點擊div的時候, function click就會被觸發。

那麼到底什麼是觀察者模式呢. 先看看生活中的觀察者模式。

好萊塢有句名言. “不要給我打電話, 我會給你打電話”. 這句話就解釋了一個觀察者模式的來龍去脈。 其中「我」是發布者, 「你」是訂閱者。

再舉個例子,我來公司面試的時候,完事之後每個面試官都會對我說:「請留下你的聯絡方式, 有消息我們會通知你」。 這裡「我」是訂閱者, 面試官是發布者。所以我不用每天或每小時都去詢問面試結果, 通訊的主動權掌握在了面試官手上。而我只需要提供一個聯絡方式。

觀察者模式可以很好的實作2個模組之間的解耦。 假如我正在一個團隊裡開發一個html5遊戲. 當遊戲開始的時候,需要載入一些圖片素材。載入好這些圖片之後開始才執行遊戲邏輯. 假設這是一個需要多人合作的專案. 我完成了Gamer和Map模組, 而我的同事A寫了一個圖片載入器loadImage。

loadImage的程式碼如下:

複製程式碼 程式碼如下:

loadImage(  imgAry,  function(){
Map.init();
Gamer.init();
} )

當圖片載入好之後, 再渲染地圖, 執行遊戲邏輯. 嗯, 這個程式運作良好. 突然有一天, 我想起應該給遊戲加上聲音功能. 我應該讓圖片載入器添上一行程式碼.
複製程式碼 程式碼如下:

loadImage(  imgAry,  function(){
Map.init();
Gamer.init();
Sount.init();
} )

可是寫這個模組的同事A去了外地旅遊. 於是我打電話給他, 餵. 你的loadImage函數在哪裡, 我能不能改一下, 改了之後有沒有副作用. 如你所想, 各種不淡定的事發生了. 如果當初我們可以這樣寫呢:
複製程式碼 程式碼如下:

loadImage.listen( ”ready', function(){
Map.init();
})
loadImage.listen( ”ready', function(){
Gamer.init();
})
loadImage.listen( ”ready', function(){
Sount.init();
})

loadImage完成之後, 它根本不關心將來會發生什麼, 因為它的工作已經完成了. 接下來它只要發布一個信號.

複製程式碼 程式碼如下:

loadImage.trigger( ”ready' );

那麼監聽了loadImage的'ready'事件的對像都會收到通知. 就像上個面試的例子. 面試官根本不關心面試者們收到面試結果後會去哪吃飯. 他只負責把麵試者的履歷蒐集到一起. 當面試結果出來時照著履歷上的電話挨個通知.

說了這麼多概念, 來一個具體的實現. 實現過程其實很簡單. 面試者把簡歷扔到一個盒子裡, 然後面試官在合適的時機拿著盒子裡的簡歷挨個打電話通知結果.

複製程式碼 程式碼如下:

イベント = function() {
var listen、log、obj、one、remove、trigger、__this;
obj = {};
__this = これ;
listen = function( key,eventfn ) { //履歴書をボックスに放り込んでください。キーは連絡先情報です。
var stack, _ref; // スタックはボックスです
stack = ( _ref = obj[key] ) != null : obj[key] = [];
return stack.push(eventfn);
};
one = function(key,eventfn){
削除(キー);
return listen( key,eventfn );
};
削除 = function( key ) {
var _ref;
return ( _ref = obj[key] ) != null _ref.length = 0 : void 0;
};
trigger = function() { //面接官が面接官に通知するために電話をかけます
var fn、スタック、_i、_len、_ref、キー;
key = Array.prototype.shift.call( 引数 );
stack = ( _ref = obj[ key ] ) != null : obj[ key ] = [];
for ( _i = 0, _len = stack.length; _i fn = stack[_i ];
if ( fn.apply( __this, argument ) === false) {
false を返します;
}
}
戻り値 {
聞いてください: 聞いてください
1:1、
削除: 削除、
トリガー: トリガー
}
}

最後に、オブザーバー モードを使用して、小さなアダルト TV アプリケーションを作成します。

コードをコピーします コードは次のとおりです:

//購読者
var AdultTv = イベント();
アダルトテレビ .listen( ”play', function( data ){
alert (「今日は誰の映画ですか」 data.name );
});
//発行者:
AdultTv .trigger( ”play', { 'name': '麻生希' } )
陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn