外觀模式 門面模式 Facade 結構型 設計模式(十三)

外觀模式(FACADE)
又稱爲門面模式
image_5c04c84e_d32
 

意圖

爲子系統中的一組接口提供一個一致的界面
Facade模式定義了一個高層接口,這一接口使得這一子系統更加易於使用。

意圖解析

隨着項目的持續發展,系統基本上都是會往功能更全面的方向發展,那麼也就意味着咱們的系統將會變得更加複雜。
系統會被劃分爲多個單獨的子系統,每一個子系統完成一部分功能,經過分工協做完成所有功能。
一個子系統也可能進一步拆分爲更小的幾個子系統。
 
程序中的文件將會愈來愈多,相互關聯也會變得更加複雜
當使用一個功能的時候,做爲客戶端
你須要弄清楚相關類之間的關係,以及正確的調用順序。
 
好比下圖中
你須要本身識別有哪些子系統,涉及哪些相關的類和方法,你須要本身保證順序(若是功能調用依賴順序的話)
image_5c04c84e_5ec
 
如同在醫院裏面,病人須要本身去排隊掛號化驗,跟每一個流程的工做人員進行協做
如同在工廠裏面,須要生產一個桌子,你親自用機器生產桌子腿,本身使用機器生產桌面...
如同你去其餘公司洽談業務,你單獨跟每一個相關業務的人員進行聯繫溝通
 
你確定想獲得,若是有一箇中間人爲你代勞
不須要面對林林總總的子系統、部門、人員...
當你須要某種服務時,只須要告訴這個中間人就行了
這個想法就是外觀模式
image_5c04c84e_38cc
 
有了facade,你就不須要跟每一個子系統進行單獨的交流了
如同在醫院裏面,對於VIP,有專人代替你掛號.....
如同在工廠裏面,有一個控制檯機器,你選擇產品,控制檯下發命令安排其餘的機器生產具體產品
如同你去其餘公司洽談業務,有一個接口人負責與你對接,他們那邊的事情都經過這我的進行安排
 
image_5c04c84e_22f4
 
外觀模式的意圖含義,如同他的名字同樣,「建築物的正面」
面對一個複雜的大樓,當你在正面遠遠望去,也就只能看到正面
在外觀模式中,形容一個龐大的複雜的系統的一個直觀的界面
藉助於Facade模式
從原來的「客戶端須要跟多個子系統進行交互」,轉變爲「只與Facade進行交互」
將客戶端與子系統進行解耦, 下降了耦合性,也下降了使用的複雜度

代碼示例

「關好門窗,防火防盜」這句話有沒有聽過?
回想一下,當你早上準備出門離開家時,你會作什麼?
假設你會關水、關燈、關門窗。
咱們建立三個類,水 燈 窗,模擬離開家的場景  
package facade;
public class Water {
public void turnOn() {
        System.out.println("打開水龍頭...");
    }   
    public void turnOff() {
        System.out.println("關閉水龍頭...");
    }
}
package facade;
public class Light {
    public void turnOn() {
        System.out.println("開燈...");
    } 
    public void turnOff() {
        System.out.println("關燈...");
    }
}
package facade;
 
public class Window {
    public void open() {
        System.out.println("開窗...");
    } 
    public void close() {
        System.out.println("關窗...");
    }
}
測試代碼
image_5c04c84f_e57
 
上面的測試代碼Test做爲客戶端程序,能夠看得出來,他直接跟Water Light Window三個類的對象進行交互
他須要調用相關的方法
也就是說Test 做爲客戶端對於「離家」這一系統的內部邏輯是瞭如指掌的--->須要斷水、關燈、關窗
他也清楚每一個類的方法
一方面增長了耦合性,另外一方面將子系統的內部細節暴露出來

優化重構

試想下,若是你家是智能家居,有一個控制檯Facade,或者說有一個手機App
他能夠控制整個家庭的設備
package facade;
 
public class Facade {
    private Water water = new Water();
    private Light light = new Light();
    private Window window = new Window();
    
    public void leaveHome(){
        water.turnOff();
        light.turnOff();
        window.close();
    }
     
    public void backHome(){
        light.turnOn();
        window.open();
    }
 
}

 

image_5c04c84f_780b
 
經過這個控制檯,客戶端程序再也不須要了解子系統的內部細節,他也不清楚每一個類到底有哪些方法
全部的交互都是經過Facade來完成的

結構

image_5c04c84f_7b08
Facade 外觀角色
客戶端調用角色,知曉子系統的全部功能與職責
一般,Facade會將全部的請求轉發委派到子系統中去,也就是說該角色沒有實際的業務、
 
SubSystem子系統角色
能夠同時有一個或者多個子系統
注意   :子系統並非說一個單獨的類,而是一個類的集合,這些類根據邏輯功能點被組織在一塊兒  
子系統並不知道Facade的存在,對於子系統來講,Facade也就只是一個客戶端程序
 
外觀模式的結構比較簡單,相似一個「封裝」提取的過程
他的 根本原則爲迪米特法則,也就是「 不要和陌生人說話」,儘量少的與其餘的對象進行交互
經過外觀模式,作到了子系統只與外觀對象交互
 
門面類個數
在門面模式中,一般只須要一個門面類,而且這個門面類只有一個實例
換句話說他極可能是一個單例
可是並非說整個系統中只能有一個門面類
門面類的個數要根據系統中子系統的個數以及業務邏輯的狀況

總結

當你 須要爲一個複雜的子系統提供一個簡單的接口時或者但願子系統可以更加獨立時,能夠考慮使用外觀模式
藉助於外觀模式,能夠實現客戶端與子系統的解耦,減小客戶端對子系統的依賴性
一旦完成解耦,就意味着子系統有良好的獨立性,也能擁有更好的擴展性
由於獨立了,就意味着單獨的子系統修改不會影響其餘系統
並且, 在多層次結構的系統中,可使用Facade模式進行層與層之間的交互,將層與層之間的耦合性下降,使他們僅僅經過facade進行交互
總之一句話,下降了使用子系統的複雜程度,下降了耦合程度,知足迪米特法則----不要和陌生人說話 
對客戶端屏蔽了子系統的組件
僅僅經過Facade, 大大減小了客戶端所須要處理的對象的數目
對於外觀模式, 若是是子系統發生變化,Facade則極有可能須要面臨修改,這不符合開閉原則 
外觀模式(門面模式)就如同咱們開篇的圖片同樣,做爲公司前臺
接待來訪賓客,一切事宜都有她來協調安排組織。
在OOP中,這個「前臺」不只是一個子系統的「正面」看到的樣子,並且還強調了她的全權負責
她提供全部的業務須要的相關方法,儘管內部調用都是子系統中的方法,她提供簡單一致的交流溝通形式 
理解了迪米特法則,那麼就比較容易理解外觀模式
外觀模式重點在於提供一個「簡化」「封裝」後的操做控制檯,讓你更容易操做整個系統,他幾乎不會涉及子系統的內部邏輯
不然,門面對象將與子系統的業務邏輯耦合,增長了耦合度。
相關文章
相關標籤/搜索