一,總體概要
1,筆者淺談
說起“門面”這個設計模式其實不論新老程序猿都是在無意中就已經運用到此模式了,就像我們美麗的JS程序員一樣不經意就使用了閉包處理問題,
1 function Employee(name) { 2 var name = name; 3 this.say = function () { 4 console.log("I am employee " + name) ; 5 } ; 6 }
代碼中“say”是一個function,Employee也是一個function這就構成了一個閉包環境,其實多數我們都是如上的定義方式,也就潛移默化的使用了閉包,O(∩_∩)O~ 讓我們繼續回來,門面這個模式很容易理解見如下圖

圖中描述的很清晰,三個子系統彼此獨立有自己的職責划分,從客戶端的角度來看是不關心它們細節的,那么如何把這三個子系統與客戶端做連線那?好的!!!這時文中的主角該亮相了,這就是門面模式它起到了一個統一入口的職責,
降低子系統之間客戶端與實現化層之間的依賴性。當在構建一個層次化的系統時,也可以同過使用Facade模式定義系統中每一層的入口,從而簡化層與層之 間的依賴關系。
文字可能會有些抽象但是慢慢來,一步步分析,現在假設有這么個場景,有兩個以完善的插件模塊,基於這個再做二次開發,我們想想這就和圖中的場景很類似了,以下是模擬代碼有助於理解
1 function HelloWorld(){ 2 this.greetPlug = new GreetPlug() ; 3 this.filterPlug = new FilterPlug() ; 4 this.hello = function(name){ 5 if(!this.filterPlug.filter(name,"zhangsan")){ 6 this.greetPlug().say(name) ; 7 } 8 } 9 } ; 10 function GreetPlug(){ 11 this.say = function(what){ 12 console.log("Hello," + what) ; 13 } 14 } ; 15 function FilterPlug(){ 16 this.filter = function(what,not){ 17 return (what === not) ? true : false ; 18 } 19 } ;
里面的HelloEorld就是相對於和門面接口,至於兩外兩個類是隱藏的,這就是大概的思路!再看兩個應用例子加深理解,如下圖

隱藏了DOM標准事件接口的細節,做了事件兼容的api。

這個大家就更熟悉了,jQuery的Ajax操作是大家平時操作相對來說比較頻繁的,沒錯它也用到了門面模式,底層是低級api做支持,門面層通過不同參數划分職能!
二,門面與迪米特法則
迪米特法則(Law of Demeter)又叫作最少知識原則(Least Knowledge Principle 簡寫LKP),就是說一個對象應當對其他對象有盡可能少的了解,不和陌生人說話。英文簡寫為: LoD.
迪米特法則的核心觀念就是類間解耦,弱耦合,只有弱耦合了以后,類的復用性才可以提高。
其實二者的關系很好理解,門面模式就是基於此法則衍生出來的解決方案,適用於特定場景的同一類問題的解決方案。下面再來看個例子,如下
現在有這么個場景------監獄內的犯人是不應該跟外面的人接觸的,當然或許會有探親的。這里的監獄就是類,里面的犯人就是類內部的信息,而監獄里的獄警就相當於迪米特法則的執行者
1 function Inmates(){ 2 this.say = function(){ 3 console.log('獄友說:我們是獄友...") ; 4 } ; 5 } ; 6 function Prisoners(){ 7 this.inmates = new Inmates() ; 8 this.helpEachOther = function(){ 9 this.inmates.say() ; 10 console.log("家人說:你和獄友之間應該互相幫助...") ; 11 } ; 12 } ; 13 function Family(){ 14 this.prisoners = new Prisoners() ; 15 this.visit = function(inmates,prisoners){ 16 this.prisoners.helpEachOther() ; 17 } ; 18 } ;
看到這樣的結果,是不是有些別扭,家人告訴犯人要與獄友好好相處,而獄友確冒出來說話。這顯然越界了,因為監獄只允許家人探望犯人,而不是隨便誰都可以見的
這里的家人和獄友有了溝通是違背迪米特法則的,所以我們需要將家人和獄友隔離開,對其進行重構
(1),定義家人類
1 function Family(){ 2 this.prisoners = new Prisoners() ; 3 this.visit = function(prisoners){ 4 console.log("家人說:") ; 5 this.prisoners.helpEachOther() ; 6 } ; 7 } ;
(2),定義犯人類
1 function Prisoners(){ 2 this.inmates = new Inmates() ; 3 this.helpEachOther = function(){ 4 console.log("犯人和獄友之間應該互相幫助...") ; 5 console.log("犯人說:") ; 6 inmates.weAreFriends() ; 7 } ; 8 } ;
(3),定義獄友類
1 function Inmates(){ 2 this.weAreFriends = function(){ 3 console.log('我們是獄友...") ; 4 } ; 5 } ;
(4),定義場景類
1 function Prison(){ 2 new Family().visit(new Prisoners()) ; 3 } ;
這樣家人和獄友就分開了,但是也表達了家人希望獄友能跟犯人互相幫助的意願。也就是兩個類通過第三個類實現信息傳遞
三,概要總結
迪米特法則的總結:
迪米特法則不希望類直接建立直接的接觸。如果真的有需要建立聯系,也希望能通過它的友元類來轉達。因此,應用迪米特法則有可能造成的一個后果就是:系統中存在大量的中介類,
這些類之所以存在完全是為了傳遞類之間的相互調用關系------這在一定程度上增加了系統的復雜度。有興趣可以研究一下設計模式的門面模式(Facade)和中介模式(Mediator),
都是迪米特法則應用的例子。
門面模式的優點:
松散耦合
門面模式松散了客戶端與子系統的耦合關系,讓子系統內部的模塊能更容易擴展和維護。
簡單易用
門面模式讓子系統更加易用,客戶端不再需要了解子系統內部的實現,也不需要跟眾多子系統內部的模塊進行交互,只需要跟門面類交互就可以了。
更好的划分訪問層次
通過合理使用Facade,可以幫助我們更好地划分訪問的層次。有些方法是對系統外的,有些方法是系統內部使用的。把需要暴露給外部的功能集中到門面中,這樣既方便客戶端使用,也很好地隱藏了內部的細節。
哈哈哈,本篇結束,未完待續,希望和大家多多交流夠溝通,共同進步(*^__^*) 嘻嘻……
