JavaScript設計模式經典之觀察者模式
觀察者模式( 又叫釋出者-訂閱者模式 )應該是最常用的模式之一. 在很多語言裡都得到大量應用. 包括我們平時接觸的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’事件的物件都會收到通知. 就像上個面試的例子. 面試官根本不關心面試者們收到面試結果後會去哪吃飯. 他只負責把面試者的簡歷蒐集到一起. 當面試結果出來時照著簡歷上的電話挨個通知.
說了這麼多概念, 來一個具體的實現. 實現過程其實很簡單. 面試者把簡歷扔到一個盒子裡, 然後面試官在合適的時機拿著盒子裡的簡歷挨個打電話通知結果.
Events = function() {
var listen, log, obj, one, remove, trigger, __this;
obj = {};
__this = this;
listen = function( key, eventfn ) { //把簡歷扔盒子, key就是聯絡方式.
var stack, _ref; //stack是盒子
stack = ( _ref = obj[key] ) != null ? _ref : obj[ key ] = [];
return stack.push( eventfn );
};
one = function( key, eventfn ) {
remove( key );
return listen( key, eventfn );
};
remove = function( key ) {
var _ref;
return ( _ref = obj[key] ) != null ? _ref.length = 0 : void 0;
};
trigger = function() { //面試官打電話通知面試者
var fn, stack, _i, _len, _ref, key;
key = Array.prototype.shift.call( arguments );
stack = ( _ref = obj[ key ] ) != null ? _ref : obj[ key ] = [];
for ( _i = 0, _len = stack.length; _i < _len; _i++ ) {
fn = stack[ _i ];
if ( fn.apply( __this, arguments ) === false) {
return false;
}
}
return {
listen: listen,
one: one,
remove: remove,
trigger: trigger
}
}
最後用觀察者模式來做一個成人電視臺的小應用.
//訂閱者
var adultTv = Event();
adultTv .listen( ”play’, function( data ){
alert ( “今天是誰的電影” + data.name );
});
//釋出者
adultTv .trigger( ”play’, { ‘name’: ‘麻生希’ } )
相關文章
- JavaScript設計模式之觀察者模式JavaScript設計模式
- 設計模式之觀察者模式設計模式
- 設計模式之-觀察者模式設計模式
- 設計模式之【觀察者模式】設計模式
- Go 設計模式之觀察者模式Go設計模式
- 設計模式之觀察者模式(一)設計模式
- PHP 設計模式之——觀察者模式PHP設計模式
- golang設計模式之觀察者模式Golang設計模式
- Java 設計模式之《觀察者模式》Java設計模式
- python設計模式之觀察者模式Python設計模式
- PHP設計模式之觀察者模式PHP設計模式
- PHP 設計模式之觀察者模式PHP設計模式
- JavaScript 設計模式之觀察者模式與釋出訂閱模式JavaScript設計模式
- JavaScript設計模式經典之代理模式JavaScript設計模式
- Java常用設計模式之觀察者模式Java設計模式
- 設計模式之觀察者模式(Observer Pattern)設計模式Server
- Java設計模式之(十二)——觀察者模式Java設計模式
- 設計模式 —— 觀察者模式設計模式
- 設計模式(觀察者模式)設計模式
- 設計模式----觀察者模式設計模式
- 【設計模式】觀察者模式設計模式
- 設計模式——觀察者模式設計模式
- JavaScript設計模式之釋出-訂閱模式(觀察者模式)-Part2JavaScript設計模式
- 折騰Java設計模式之觀察者模式Java設計模式
- 17.java設計模式之觀察者模式Java設計模式
- PHP設計模式-觀察者模式PHP設計模式
- Java設計模式-觀察者模式Java設計模式
- 設計模式解析:觀察者模式設計模式
- 設計模式 #6 (觀察者模式)設計模式
- JS設計模式(觀察者模式)JS設計模式
- 設計模式(十六)觀察者模式設計模式
- 設計模式(9) 觀察者模式設計模式
- 設計模式-觀察者模式上設計模式
- 設計模式-觀察者模式下設計模式
- 掌握設計模式--觀察者模式設計模式
- 設計模式實戰 - 觀察者模式設計模式
- PHP設計模式(5)—— 觀察者模式PHP設計模式
- 設計模式解析-1:觀察者模式設計模式
- 《Head First 設計模式》:觀察者模式設計模式