国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

JavaScript觀察者模式(經典)

2019-11-20 11:02:56
字體:
來源:轉載
供稿:網友

Observer模式也叫觀察者模式,是由GoF提出的23種軟件設計模式的一種。Observer模式是行為模式之一,它的作用是當一個對象的狀態發生變化時,能夠自動通知其他關聯對象,自動刷新對象狀態。

Observer模式的概念

Observer模式是行為模式之一,它的作用是當一個對象的狀態發生變化時,能夠自動通知其他關聯對象,自動刷新對象狀態。
Observer模式提供給關聯對象一種同步通信的手段,使某個對象與依賴它的其他對象之間保持狀態同步。

Observer模式的角色:

Subject(被觀察者)
被觀察的對象。當需要被觀察的狀態發生變化時,需要通知隊列中所有觀察者對象。Subject需要維持(添加,刪除,通知)一個觀察者對象的隊列列表。
ConcreteSubject
被觀察者的具體實現。包含一些基本的屬性狀態及其他操作。
Observer(觀察者)
接口或抽象類。當Subject的狀態發生變化時,Observer對象將通過一個callback函數得到通知。
ConcreteObserver
觀察者的具體實現。得到通知后將完成一些具體的業務邏輯處理。

觀察者模式( 又叫發布者-訂閱者模式 )應該是最常用的模式之一. 在很多語言里都得到大量應用. 包括我們平時接觸的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': ‘麻生希' } )

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 南丹县| 邵阳市| 旬阳县| 饶平县| 定州市| 会同县| 太保市| 襄樊市| 乃东县| 湘潭县| 青河县| 卓资县| 五家渠市| 永康市| 宣武区| 西宁市| 固原市| 清远市| 富锦市| 威远县| 双柏县| 龙井市| 新绛县| 攀枝花市| 定结县| 谢通门县| 工布江达县| 台北县| 奈曼旗| 右玉县| 文水县| 区。| 库尔勒市| 墨竹工卡县| 广元市| 呼伦贝尔市| 日土县| 宁河县| 祁门县| 郸城县| 三穗县|