Facade模式在本文架構裡佔有重要角色,關於這個模式很多JavaScript類別庫或框架裡都有體現,其中最大的作用,就是包括High level的API,以此來隱藏具體的實現,這就是說,我們只暴露接口,內部的實現我們可以自己做主,也意味著內部實現的代碼可以很容易的修改和更新,比如今天你是用jQuery來實現的,明天又想換YUI了,這就非常方便了。
下面這個例子了,可以看到我們提供了很多私有的方法,然後透過揭露一個簡單的API來讓外界執行呼叫內部的方法:
var module = (function () { var _private = { i: 5, get: function () { console.log('current value:' + this.i); }, set: function (val) { this.i = val; }, run: function () { console.log('running'); }, jump: function () { console.log('jumping'); } }; return { facade: function (args) { _private.set(args.val); _private.get(); if (args.run) { _private.run(); } } } } ()); module.facade({run:true, val:10}); //outputs current value: 10, running
Facade和下面我們所說的mediator的差異是,facade只提供現有存在的功能,而mediator可以增加新功能。
Mediator模式
在講modiator之前,我們先來舉個例子,機場飛行控制系統,也就是傳說中的塔台,具有絕對的權利,他可以控制任何一架飛機的起飛和降落時間以及地方,而飛機和飛機之前不允許通信,也就是說塔台是機場的核心,mediator就相當於這個塔台。
mediator就是用在程式裡有多個模組,而你又不想讓各個模組有依賴的話,那透過mediator模式可以達到集中控制的目的。實際場景中也是,mediator封裝了許多不想乾的模組,讓他們透過mediator連結在一起,同時也鬆開他們,使得他們之間必須透過mediator才能通訊。
那mediator模式的優點是什麼?那就是解耦,如果你之前對觀察者模式比較了解的話,那理解下面的mediator圖就相對簡單多了,下圖是一個high level的mediator模式圖:
想想一下,各模組是發布者,mediator既是發布者又是訂閱者。
Module 1向Mediator廣播一個實際,說需要做某事
Mediator捕獲訊息以後,立即啟動處理訊息需要使用的Module 2,Module 2處理結束以後返回訊息給Mediator
同時,Mediator也啟動了Module 3,當接受Module 2 返回訊息的時候自動記錄日誌到Module 3裡
可以看到,各模組之間並沒有通信,另外Mediator也可以實現監控各模組狀態的功能,例如如果Module 3出錯了,Mediator可以暫時只想其它模組,然後重啟Module 3,然後繼續執行。
回顧一下,可以看到,Mediator的優點是:鬆散耦合的模組由同一的Mediator來控制,模組只需要廣播和監聽事件就可以了,而模組之間不需要直接聯繫,另外,一次資訊的處理可以使用多個模組,也方便我們以後統一的加入新的模組到現有的控制邏輯裡。
確定是:由於所有的模組直接都不能直接通信,所有相對來說,性能方面可能會有少許下降,但是我認為這是值得的。
我們根據上面的講解來一個簡單的Demo:
var mediator = (function(){ var subscribe = function(channel, fn){ if (!mediator.channels[channel]) mediator.channels[channel] = []; mediator.channels[channel].push({ context: this, callback: fn }); return this; }, publish = function(channel){ if (!mediator.channels[channel]) return false; var args = Array.prototype.slice.call(arguments, 1); for (var i = 0, l = mediator.channels[channel].length; i < l; i++) { var subscription = mediator.channels[channel][i]; subscription.callback.apply(subscription.context, args); } return this; }; return { channels: {}, publish: publish, subscribe: subscribe, installTo: function(obj){ obj.subscribe = subscribe; obj.publish = publish; } }; }());
然後有2個模組分別呼叫:
//Pub/sub on a centralized mediator mediator.name = "tim"; mediator.subscribe('nameChange', function(arg){ console.log(this.name); this.name = arg; console.log(this.name); }); mediator.publish('nameChange', 'david'); //tim, david //Pub/sub via third party mediator var obj = { name: 'sam' }; mediator.installTo(obj); obj.subscribe('nameChange', function(arg){ console.log(this.name); this.name = arg; console.log(this.name); }); obj.publish('nameChange', 'john'); //sam, john
應用Facade: 應用程式核心的抽象
一個facade是作為應用程式核心的一個抽象來工作的,在mediator和模組之間負責通信,各個模組只能透過這個facade來和程式核心進行通訊。作為抽象的職責是確保任何時候都能為這些模組提供一個一致的介面(consistent interface),和sendbox controller的角色比較類似。所有的模組組件透過它和mediator通信,所以facade需要是可靠的,可信賴的,同時作為為模組提供介面的功能,facade還需要扮演另外一個角色,那就是安全控制,也就是決定程式的哪個部分可以被一個模組訪問,模組組件只能調用他們自己的方法,並且不能訪問任何未授權的內容。例如,一個模組可能會廣播dataValidationCompletedWriteToDB,這裡的安全檢查需要確保模組擁有資料庫的寫入權限。
總之,mediator只有在facade授權偵測以後才能進行資訊處理。
應用Mediator:應用程式的核心
Mediator是作為應用程式核心的角色來工作的,我們簡單地來說一下他的職責。最核心的工作就是管理模組的生命週期(lifecycle),當這個核心撲捉到任何資訊進來的時候,他需要判斷程式如何來處理——也就是說決定啟動或停止哪一個或一些模組。當一個模組開始啟動的時候,它應該能否自動執行,而不需要應用程式核心來決定是否該執行(例如,是否要在DOM ready的時候才能執行),所以說需要模組自身需要去判定。
你可能還有問題,就是一個模組在什麼情況下才會停止。當程式偵測到一個模組失敗了,或者是出錯了,程式需要做決定來防止繼續執行該模組裡的方法,以便這個元件可以重新啟動,目的主要是提高使用者體驗。
另外,該核心應該可以動態新增或刪除模組,而不影響其他任何功能。常見的例子是,一個模組在頁面加載初期是不可用,但是用戶操作以後,需要動態加載這個模組然後執行,就像Gmail裡的chat聊天功能一樣,從性能優化的目的來看,應該是很好理解的吧。
異常錯誤處理,也是由應用程式核心來處理的,另外各模組在廣播訊息的時候,也廣播任何錯誤到該核心裡,以便程式核心可以根據情況去停止/重啟這些模組。這也是鬆散耦合架構一個很重要的部分,我們不需要手動改變任何模組,透過mediator使用發布/訂閱就可以來做到這一點。
以上是JavaScript設計Facade模式和Mediator模式用法區別實例詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!