1、前言javascript
門面模式,也稱Facade(外觀)模式。核心的兩點做用——html
1> 簡化類的接口(讓接口變得更加容易理解、容易應用、更加符合對應業務),來掩蓋一個很是不一樣或者複雜的實現java
2> 消除類與使用它的客戶代碼之間的耦合程序員
能夠把門面模式想成是簡化API來展現給其餘開發人員,一般都是能夠提升可用性。編程
2、舉例設計模式
例子1、事件監聽數組
function addEvent(el, type, fn) { if (window.addEventListener) { el.addEventListener(type, fn, false); } else if (window.attachEvent) { el.attachEvent('on' + type, fn); } else { el['on' + type] = fn; } }
有了這個門面,就有了一種爲DOM節點添加事件監聽器的簡便方法,就沒必要再爲每次爲一個元素添加事件監聽器都得針對瀏覽器間的差別進行檢查而煩惱。瀏覽器
例子2、組合函數函數
function a(x) { // do stuff here... } function b(y) { // do stuff here... } function ab(x, y) { a(x); b(y); }
分別提供a、b和ab這幾個函數能夠得到更多粒度控制和靈活性。工具
例子3、工具函數
在處理跨瀏覽器的開發問題時,最好建立一些門面函數。若是涉及一個大型庫,那麼最好把其中全部的工具元素聚攏在一塊兒,這樣更好用,訪問起來也更方便。鑑於各類瀏覽器在事件處理表現出來的大量差別,開發一個事件工具頗有必要。
var DED = window.DED || {}; DED.util.Event = { getEvent: function(e) { return e || window.event; }, getTarget: function(e) { return e.target || e.srcElement; }, stopPropagation: function(e) { if (e.stopPropagation) { // W3 interface e.stopPropagation(); } else { // IE interface e.cancelable(); } }, preventDefault: function(e) { if (e.preventDefault) { // W3 interface e.preventDefault(); } else { // IE interface e.returnValue = false; } }, stopEvent: function(e) { DED.util.stopPropagation(e); DED.util.preventDefault(e); } };
應用上面的例子
addEvent($('#emample'), 'click', function(e) { // who clicked me console.log(DED.util.Event.getTarget(e)); // stop propagation and prevent the default action DED.util.Event.stopEvent(e); });
例子4、結合其餘模式一塊兒應用
門面模式不是必須單獨使用。他們也能夠與其餘模式集成,如Module模式。Module模式的實例包含不少已經定義的私有方法。而後使用門面模式提供一個簡單的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(); } } }; }());
3、適用場景
1.判斷是否應該應用門面模式的關鍵在於辨認那些反覆成組出現的代碼。若是函數b出如今函數a以後這種狀況常常出現,那麼也許你應該考慮添加一個把這兩個函數組合起來的門面函數。
2.在覈心工具代碼中加入門面函數的另外一個目的是應對js內置函數在不一樣瀏覽器中的不一樣表現。這樣作並非由於不能直接使用這些API,而是由於在處理跨瀏覽器的差別問題時最好的解決方法就是把這些差別抽取到門面方法中。它們能夠提供一個更一致的接口。
4、優點
1.門面模式的目的就是讓程序員過得更輕鬆一些。編寫一次組合代碼,而後就能夠反覆使用它,這有助於節省時間和精力。它們能夠替你把硬骨頭啃掉,而且提供了一個處理常見問題和任務的簡化接口。
2.門面方法方便了開發人員,而且提供了較高層的功能,若是不用門面模式的話,這些功能實現起來可能會乏味而又費力。
3.它們還能下降對外部代碼的依賴程度,這爲應用系統的開發增長了一些額外的靈活性。經過使用門面模式,能夠避免與下層子系統緊密耦合。這樣能夠對這個系統進行修改而不會影響到客戶代碼。
5、劣勢
有時候門面元素也會帶來一些沒必要要的額外負擔。方便的東西不必定就得用。門面模式經常被濫用。有時相比一個龐雜的門面函數,其組成函數在粒度方面更有吸引力。這是由於門面函數可能經常會執行一些你並不須要的任務。
6、結論
門面模式可用來建立便利函數,這些函數爲執行各類複雜任務提供了一個簡單的接口。它們使代碼更容易維護和理解。它們還能弱化子系統和客戶代碼的耦合。便利方法有助於簡化常見的重複性任務,以及把常常相伴出現的經常使用函數組合在一塊兒。這個模式在DOM腳本編程這種須要面對各類不一致 的瀏覽器接口的環境中很經常使用。可是要注意,當使用門面模式的時候,要試着瞭解涉及的任何性能成本,並確認是否值得抽象。
源自:JavaScript設計模式(人民郵電出版社)——第十章,門面模式
參考:《JavaScript設計模式》 —— 9.9 Facade(外觀)模式