外觀模式是一種使用頻率很是高,但理解較爲簡單的設計模式,經過引入一個外觀角色來簡化客戶端與子系統之間的操做,爲複雜的子系統調用提供一個統一的入口,使子系統與客戶端的耦合度下降,且客戶端調用很是方便。java
在大多數狀況下,一個網站都會提供一個網站首頁。網站首頁通常做爲整個網站的入口,提供了通往各個子欄目的超連接,用戶經過該首頁便可進入子欄目獲取所需信息。對於用戶而言只需記住網站首頁網站 URL,而無須記住每一個子欄目的網址。網站首頁做爲用戶訪問子欄目的入口,是網站的外觀角色。用戶經過它能夠方便地訪問子欄目,固然也能夠繞過它直接訪問子欄目。
若是沒有外觀角色,即沒有爲網站提供一個首頁,每一個用戶須要記住全部子欄目的 URL,不只會讓系統耦合度增長,用戶與系統的交互也會異常複雜。編程
外部與一個子系統的通訊必須經過一個統一的外觀對象進行,爲子系統中的一組接口提供一個一致的界面,外觀模式定義了一個高層接口,這個接口使得這一子系統更加易於使用。設計模式
外觀模式沒有一個通常化的類圖描述,這裏以類圖做爲外觀模式的描述形式之一。
測試
Facade(外觀角色)網站
在客戶端能夠調用這個角色的方法,在外觀角色中能夠知道相關子系統的功能和責任;在正常狀況下,它將全部從客戶端發來的請求委派到相應子系統,傳遞給相應的子系統對象處理。this
SubSystem(子系統角色)設計
在軟件系統中能夠同時有一個或多個子系統角色,每個子系統均可以被客戶端直接調用,或被外觀角色調用,處理外觀類傳過來的請求;子系統並不知道外觀的存在,對於子系統而言,外觀僅僅是另一個客戶端而言。3d
一個電源總開關能夠控制四盞燈、一個風扇、一臺空調和一臺電視機的啓動和關閉。經過該電源總開關能夠同時控制全部上述電器設備,使用外觀模式設計該系統。
code
子系統類 Light對象
public class Light { private String position; public Light(String position) { this.position = position; } public void on() { System.out.println(this.position + "燈打開"); } public void off() { System.out.println(this.position + "燈打開"); } }
子系統類 Fan
public class Fan { public void on() { System.out.println("風扇打開"); } public void off() { System.out.println("風扇關閉"); } }
子系統類 AirConditioner
public class AirConditioner { public void on() { System.out.println("空調打開"); } public void off() { System.out.println("空調關閉"); } }
子系統類 Televison
public class Television { public void on() { System.out.println("電視機打開"); } public void off() { System.out.println("電視機關閉"); } }
外觀類 GeneralSwitchFacade
public class GeneralSwitchFacade { private Light[] lights = new Light[4]; private Fan fan; private AirConditioner ac; private Television tv; public GeneralSwitchFacade() { lights[0] = new Light("左前"); lights[1] = new Light("右前"); lights[2] = new Light("左後"); lights[3] = new Light("右後"); fan = new Fan(); ac = new AirConditioner(); tv = new Television(); } public void on() { lights[0].on(); lights[1].on(); lights[2].on(); lights[3].on(); fan.on(); ac.on(); tv.on(); } public void off() { lights[0].off(); lights[1].off(); lights[2].off(); lights[3].off(); fan.off(); ac.off(); tv.off(); } }
測試類 Client
public class Client { public static void main(String[] args) { GeneralSwitchFacade gsf = new GeneralSwitchFacade(); gsf.on(); System.out.println("-------------"); gsf.off(); } }
運行結果
外觀模式優勢以下:
外觀模式缺點以下:
如下狀況可使用外觀模式:
爲了節約資源,通常將外觀類設計爲單例類,但這並不意味整個系統只有一個外觀類。一個系統中能夠設計多個外觀類,每一個外觀類都負責和一些特定的子系統交互,向用戶提供相應的業務功能
外觀模式的用意是爲子系統提供一個集中化和簡化的溝通渠道,而不是向子系統加入新的行爲,新的行爲的增長應經過修改原有子系統類或增長新的子系統類來實現,不能經過外觀類來實現
迪米特法則要求你與直接的朋友通訊。外觀模式創造出一個外觀對象,將客戶端所涉及的屬於一個子系統的協做夥伴的數量減到最少。外觀類充當了客戶類與子系統類之間的第三者,下降了客戶類與子系統之間的耦合度。外觀模式是實現代碼重構以達到迪米特法則要求的一個強有力的武器。
外觀模式最大的缺點是違背了開閉原則,當增長新的子系統或移除子系統時需修改外觀類,能夠經過引入抽象外觀類在必定程度上解決該問題,客戶端針對抽象外觀類編程。對於新的業務需求,不修改原有外觀類,對應增長一個新的具體外觀類,由新的具體外觀類來關聯新的子系統對象。