Gof定義
爲子系統中的一組接口提供一個一致的界面,Façade模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。
先來看個小例子,假設我們需要開發一個坦克模擬系統用於模擬坦克車在各種作戰環境中的行爲,其中坦克系統由引擎、控制器、車輪、車身等各子系統構成。就會有下面這些類的產生
public class Wheel{ } public class Engine{ } public class Controller{ } public class BodyWork{ }
不同的場景中的要求都不一樣,可能會用到某些子系統,也可能不會用到,這些不同的場景就相當是外部接口,這些場景和子系統的關係如下圖:
上圖中的關係感覺很混亂,場景和子系統之間的耦合度很高,要降低這種耦合度,就要使和場景之間交互的不是這些子系統了,而是相對單一的一箇中間層,如下圖:
上圖的Facade就將子系統隱藏了,不同的場景都是直接和Facade交互。
動機
上面圖1方案的問題在於組件的客戶和組件中各種複雜的子系統有了過多的耦合,隨着外部客戶程序和各子系統的演化,這種過多的耦合面臨很多變化的挑戰。如何簡化外部客戶程序和系統間的交互接口?如何將外部客戶程序的演化和內部子系統的變化之間的依賴相互解耦?這就要用到Facade模式,先來看結構圖:
代碼實現,先定義一些子系統類
public class Wheel { public void WAction1() { } public void WAction2() { } } public class Engine { public void EAction1() { } public void EAction2() { } } public class Controller { public void CAction1() { } public void CAction2() { } } public class BodyWork { public void BAction1() { } public void BAction2() { } }
Facade類,用來組合這些子系統
public class TankFacade { Wheel[] wheels = new Wheel[4]; Engine[] engines = new Engine[4]; BodyWork bodywork = new BodyWork(); Controller controller = new Controller(); public void Start() { //用到子系統中的一個或多個 } public void Stop() { //用到子系統中的一個或多個 } public void Run() { //用到子系統中的一個或多個 } public void Shot() { //用到子系統中的一個或多個 } }
客戶端調用
public class App { static void Main() { TankFacade facade = new TankFacade(); //可以根據不同場景的需要來選擇調用相應的方法 //在客戶處之需要使用Facade就可以,不需要知道子系統的實現 //就起到了和子系統解耦的作用 facade.Start(); facade.Run(); facade.Shot(); facade.Stop(); } }
Facade模式的幾個要點
從客戶程序的角度來看, Facade模式不僅簡化了整個組件系統的接口,同時對於組件內部與外部客戶程序來說,從某種程度上也達到了一種“解耦”的效果——內部子系統的任何變化不會影響到Façade接口的變化。
Façade設計模式更注重從架構的層次去看整個系統,而不是單個類的層次。Façade很多時候更是一種架構設計模式。
注意區分Façade模式、Adapter模式、Bridge模式與Decorator模式。Façade模式注重簡化接口,Adapter模式注重轉換接口,Bridge模式注重分離接口(抽象)與其實現,Decorator模式注重穩定接口的前提下爲對象擴展功能。