JavaScript觀察者模式(經(jīng)典)
Observer模式也叫觀察者模式,是由GoF提出的23種軟件設(shè)計(jì)模式的一種。Observer模式是行為模式之一,它的作用是當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生變化時(shí),能夠自動(dòng)通知其他關(guān)聯(lián)對(duì)象,自動(dòng)刷新對(duì)象狀態(tài)。
Observer模式的概念
Observer模式是行為模式之一,它的作用是當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生變化時(shí),能夠自動(dòng)通知其他關(guān)聯(lián)對(duì)象,自動(dòng)刷新對(duì)象狀態(tài)。
Observer模式提供給關(guān)聯(lián)對(duì)象一種同步通信的手段,使某個(gè)對(duì)象與依賴它的其他對(duì)象之間保持狀態(tài)同步。
Observer模式的角色:
Subject(被觀察者)
被觀察的對(duì)象。當(dāng)需要被觀察的狀態(tài)發(fā)生變化時(shí),需要通知隊(duì)列中所有觀察者對(duì)象。Subject需要維持(添加,刪除,通知)一個(gè)觀察者對(duì)象的隊(duì)列列表。
ConcreteSubject
被觀察者的具體實(shí)現(xiàn)。包含一些基本的屬性狀態(tài)及其他操作。
Observer(觀察者)
接口或抽象類。當(dāng)Subject的狀態(tài)發(fā)生變化時(shí),Observer對(duì)象將通過(guò)一個(gè)callback函數(shù)得到通知。
ConcreteObserver
觀察者的具體實(shí)現(xiàn)。得到通知后將完成一些具體的業(yè)務(wù)邏輯處理。
觀察者模式( 又叫發(fā)布者-訂閱者模式 )應(yīng)該是最常用的模式之一. 在很多語(yǔ)言里都得到大量應(yīng)用. 包括我們平時(shí)接觸的dom事件. 也是js和dom之間實(shí)現(xiàn)的一種觀察者模式.
div.onclick = function click (){ alert ( ”click' ) }
只要訂閱了div的click事件. 當(dāng)點(diǎn)擊div的時(shí)候, function click就會(huì)被觸發(fā).
那么到底什么是觀察者模式呢. 先看看生活中的觀察者模式。
好萊塢有句名言. “不要給我打電話, 我會(huì)給你打電話”. 這句話就解釋了一個(gè)觀察者模式的來(lái)龍去脈。 其中“我”是發(fā)布者, “你”是訂閱者。
再舉個(gè)例子,我來(lái)公司面試的時(shí)候,完事之后每個(gè)面試官都會(huì)對(duì)我說(shuō):“請(qǐng)留下你的聯(lián)系方式, 有消息我們會(huì)通知你”。 在這里“我”是訂閱者, 面試官是發(fā)布者。所以我不用每天或者每小時(shí)都去詢問(wèn)面試結(jié)果, 通訊的主動(dòng)權(quán)掌握在了面試官手上。而我只需要提供一個(gè)聯(lián)系方式。
觀察者模式可以很好的實(shí)現(xiàn)2個(gè)模塊之間的解耦。 假如我正在一個(gè)團(tuán)隊(duì)里開(kāi)發(fā)一個(gè)html5游戲. 當(dāng)游戲開(kāi)始的時(shí)候,需要加載一些圖片素材。加載好這些圖片之后開(kāi)始才執(zhí)行游戲邏輯. 假設(shè)這是一個(gè)需要多人合作的項(xiàng)目. 我完成了Gamer和Map模塊, 而我的同事A寫了一個(gè)圖片加載器loadImage.
loadImage的代碼如下
loadImage( imgAry, function(){ Map.init(); Gamer.init(); } )
當(dāng)圖片加載好之后, 再渲染地圖, 執(zhí)行游戲邏輯. 嗯, 這個(gè)程序運(yùn)行良好. 突然有一天, 我想起應(yīng)該給游戲加上聲音功能. 我應(yīng)該讓圖片加載器添上一行代碼.
loadImage( imgAry, function(){ Map.init(); Gamer.init(); Sount.init(); } )
可是寫這個(gè)模塊的同事A去了外地旅游. 于是我打電話給他, 喂. 你的loadImage函數(shù)在哪, 我能不能改一下, 改了之后有沒(méi)有副作用. 如你所想, 各種不淡定的事發(fā)生了. 如果當(dāng)初我們能這樣寫呢:
loadImage.listen( ”ready', function(){ Map.init(); }) loadImage.listen( ”ready', function(){ Gamer.init(); }) loadImage.listen( ”ready', function(){ Sount.init(); })
loadImage完成之后, 它根本不關(guān)心將來(lái)會(huì)發(fā)生什么, 因?yàn)樗墓ぷ饕呀?jīng)完成了. 接下來(lái)它只要發(fā)布一個(gè)信號(hào).
loadImage.trigger( ”ready' );
那么監(jiān)聽(tīng)了loadImage的'ready'事件的對(duì)象都會(huì)收到通知. 就像上個(gè)面試的例子. 面試官根本不關(guān)心面試者們收到面試結(jié)果后會(huì)去哪吃飯. 他只負(fù)責(zé)把面試者的簡(jiǎn)歷搜集到一起. 當(dāng)面試結(jié)果出來(lái)時(shí)照著簡(jiǎn)歷上的電話挨個(gè)通知.
說(shuō)了這么多概念, 來(lái)一個(gè)具體的實(shí)現(xiàn). 實(shí)現(xiàn)過(guò)程其實(shí)很簡(jiǎn)單. 面試者把簡(jiǎn)歷扔到一個(gè)盒子里, 然后面試官在合適的時(shí)機(jī)拿著盒子里的簡(jiǎn)歷挨個(gè)打電話通知結(jié)果.
Events = function() { var listen, log, obj, one, remove, trigger, __this; obj = {}; __this = this; listen = function( key, eventfn ) { //把簡(jiǎn)歷扔盒子, key就是聯(lián)系方式. 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 } }
最后用觀察者模式來(lái)做一個(gè)成人電視臺(tái)的小應(yīng)用.
//訂閱者 var adultTv = Event(); adultTv .listen( ”play', function( data ){ alert ( “今天是誰(shuí)的電影” + data.name ); }); //發(fā)布者 adultTv .trigger( ”play', { ‘name': ‘麻生希' } )
- JavaScript觀察者模式原理與用法實(shí)例詳解
- 原生javascript實(shí)現(xiàn)類似vue的數(shù)據(jù)綁定功能示例【觀察者模式】
- PHP觀察者模式實(shí)例分析【對(duì)比JS觀察者模式】
- JavaScript設(shè)計(jì)模式之觀察者模式實(shí)例詳解
- JavaScript設(shè)計(jì)模式之觀察者模式(發(fā)布訂閱模式)原理與實(shí)現(xiàn)方法示例
- JS設(shè)計(jì)模式之觀察者模式實(shí)現(xiàn)實(shí)時(shí)改變頁(yè)面中金額數(shù)的方法
- JavaScript原生實(shí)現(xiàn)觀察者模式的示例
- JavaScript編程設(shè)計(jì)模式之觀察者模式(Observer Pattern)實(shí)例詳解
- javascript觀察者模式實(shí)現(xiàn)自動(dòng)刷新效果
- JavaScript觀察者模式(publish/subscribe)原理與實(shí)現(xiàn)方法
- 深入理解Javascript中的觀察者模式
- Javascript設(shè)計(jì)模式之觀察者模式(推薦)
- 學(xué)習(xí)JavaScript設(shè)計(jì)模式之觀察者模式
- 怎樣用JavaScript實(shí)現(xiàn)觀察者模式
相關(guān)文章
基于JavaScript實(shí)現(xiàn)文件共享型網(wǎng)站
Any?Share?是一種簡(jiǎn)單、輕量、快速的文件共享服務(wù)。使用?Javascript?編寫,并搭建在?Firebase?平臺(tái)。本文將利用它實(shí)現(xiàn)創(chuàng)建文件共享型網(wǎng)站,感興趣的可以了解一下2022-11-11JavaScript判斷表單中多選框checkbox選中個(gè)數(shù)的方法
這篇文章主要介紹了JavaScript判斷表單中多選框checkbox選中個(gè)數(shù)的方法,涉及javascript針對(duì)checkbox復(fù)選框的遍歷與判斷技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-08-08ECMAScript 6即將帶給我們新的數(shù)組操作方法前瞻
這篇文章主要介紹了ECMAScript 6即將帶給我們新的數(shù)組操作方法前瞻,需要的朋友可以參考下2015-01-01JavaScript獲取css行間樣式,內(nèi)連樣式和外鏈樣式的簡(jiǎn)單方法
下面小編就為大家?guī)?lái)一篇JavaScript獲取css行間樣式,內(nèi)連樣式和外鏈樣式的簡(jiǎn)單方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-07-07Bootstrap中的Dropdown下拉菜單更改為懸停(hover)觸發(fā)
在使用bootstrap制作響應(yīng)式導(dǎo)航條時(shí),dropdown組件用的比較多,dropdown默認(rèn)鼠標(biāo)左鍵單擊才展開(kāi),如果使用鼠標(biāo)放上去(hover)就展開(kāi)則會(huì)省去點(diǎn)擊時(shí)間,這樣能提高效率,下面小編給大家解答下實(shí)現(xiàn)思路2016-08-08