概述
想想我們小時候玩的四驅車,裏面的構造很複雜,馬達,舵機,電池組等等,而我們控制它卻非常簡單,只要打開電池開關,他就可以跑。我們其實不用知道它裏面是如何工作,只要知道撥動開關它就可以工作就行了,這個開關其實就四驅車給我們的一個友好的組件,使得我們可以很方便的控制它。
外觀模式其實定義了一個高層接口,該接口爲子系統中的一組接口提供一個一致的界面,使得這一子系統更加容易使用。
類圖和樣例
在這個對象圖中,出現了兩個角色:
外觀(Facade)角色:客戶端可以調用這個角色的方法。此角色知曉相關的(一個或者多個)子系統的功能和責任。在正常情況下,本角色會將所有從客戶端發來的請求委派到相應的子系統去。
子系統(subsystem)角色:可以同時有一個或者多個子系統。每一個子系統都不是一個單獨的類,而是一個類的集合。每一個子系統都可以被客戶端直接調用,或者被外觀角色調用。子系統並不知道外觀的存在,對於子系統而言,外觀僅僅是另外一個客戶端而已。
///////P: 不過是多加了一層調用結構類: Compiler
- #include<iostream>
- using namespace std;
- class Scanner
- {
- public:
- void Scan() { cout<<"詞法分析"<<endl; }
- };
- class Parser
- {
- public:
- void Parse() { cout<<"語法分析"<<endl; }
- };
- class GenMidCode
- {
- public:
- void GenCode() { cout<<"產生中間代碼"<<endl; }
- };
- class GenMachineCode
- {
- public:
- void GenCode() { cout<<"產生機器碼"<<endl;}
- };
- //高層接口 Fecade
- class Compiler
- {
- public:
- void Run()
- {
- Scanner scanner;
- Parser parser;
- GenMidCode genMidCode;
- GenMachineCode genMacCode;
- scanner.Scan();
- parser.Parse();
- genMidCode.GenCode();
- genMacCode.GenCode();
- }
- };
- //client
- int main()
- {
- Compiler compiler;
- compiler.Run();
- return 0;
- }
-
1.Facade模式對客戶屏蔽了子系統組件,因而減少了客戶處理的對象的數目並使得子系統使用起來更加方便。
2.Facade模式實現了子系統與客戶之間的鬆耦合關係,而子系統內部的功能組件往往是緊耦合的。鬆耦合關係使得子系統的組件變化不會影響到它的客戶。
3.如果應用需要,它並不限制它們使用子系統類。因此你可以在系統易用性與通用性之間選擇。
4. 在外觀模式中,通常只需要一個外觀類,並且此外觀類只有一個實例,換言之它是一個單例類。當然這並不意味着在整個系統裏只能有一個外觀類,而僅僅是說對每一個子系統只有一個外觀類。或者說,如果一個系統有好幾個子系統的話,每一個子系統有一個外觀類,整個系統可以有數個外觀類。
5. 外觀模式的用意是爲子系統提供一個集中化和簡化的溝通管道,而不建議向子系統加入新的行爲。
6. 外觀模式注重的是簡化接口,它更多的時候是從架構的層次去看整個系統,而並非單個類的層次。
適用性和優缺點
適用性
1.爲一個複雜子系統提供一個簡單接口。
2.提高子系統的獨立性。
3.在層次化結構中,可以使用Facade模式定義系統中每一層的入口。
優點
1. 鬆散耦合
外觀模式鬆散了客戶端與子系統的耦合關係,讓子系統內部的模塊能更容易擴展和維護。即要點2.
2. 簡單易用
外觀模式讓子系統更加易用,客戶端不再需要了解子系統內部的實現,也不需要跟衆多子系統內部的模塊進行交互,只需要跟外觀交互就可以了,相當於外觀類爲外部客戶端使用子系統提供了一站式服務。
3. 更好的劃分訪問層次
通過合理使用Facade,可以幫助我們更好的劃分訪問的層次。有些方法是對系統外的,有些方法是系統內部使用的。把需要暴露給外部的功能集中到外觀中,這樣既方便客戶端使用,也很好的隱藏了內部的細節。
缺點
過多的或者是不太合理的Facade也容易讓人迷惑,到底是調用Facade好呢,還是直接調用模塊好。