在實際開發時,面對一個大的系統,總是會將一個大的系統分成若干個子系統,等子系統完成之後,再分別調用對應的子系統來完成對應的整體功能,這樣有利於降低系統的復雜性;最終進行實現某個具體的功能時,我們將對應的子系統進行組合就好了;但是,子系統那麼多,關系那麼復雜,組合形成一個完整的系統,是存在難度的。
我們在使用visual studio進行編譯C++代碼時,你只是在菜單中選擇了Build,然後visual studio就開始了一堆的編譯工作;你應該知道,因為你的一個簡單的Build動作,編譯器在後台會進行語法分析,生成中間代碼,生成匯編代碼,鏈接成可執行程序或庫等等動作;而這一切,作為只是開發程序的我們,而不用去理解編譯器在做什麼的,編譯器向我們隱藏了背後的一系列復雜操作,而只提供一個Build按鈕,這個Build按鈕,就可以執行一切的操作;當單擊這個Build按鈕時,Build在幕後,將任務分發給不同的子系統去完成,最終子系統進行協作完成了整個的編譯任務。而這樣隱藏一些復雜操作,只提供一個更高層的統一接口,就是我今天總結的外觀模式。
外觀模式,很多人也把它叫做門面模式。在GOF的《設計模式:可復用面向對象軟件的基礎》一書中對外觀模式是這樣說的:將子系統中的一組接口提供一個一致的界面,外觀模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。細細的理解這句話;子系統中的一組接口,就好比上面舉得例子中的語法分析,生成中間代碼,生成匯編代碼,鏈接成可執行程序或庫;外觀模式定義的一個高層接口,就好比上面說的Build按鈕,通過這樣的一個Build按鈕,讓編譯器更加容易使用,對於這一點,從Linux C++/C轉Windows C++/C的程序員是最有體會的。visual studio提供的強大功能,只需要一個Build按鈕,就可以進行Build動作,而不需要去寫makefile文件,然後再去執行一些命令進行編譯。
Facade:知道哪些子系統類負責處理請求,並且將客戶的請求代理給適當的子系統對象;
SubSystem:實現子系統具體的功能;處理由Facade對象指派的任務;但是,SubSystem沒有Facade的任何相關信息,也就是說,沒有指向Facade的指針。
Client通過發送請求給Facade的方式與子系統進行通信,而不直接與子系統打交道,Facade將這些消息轉發給適當的子系統對象。盡管是子系統中的有關對象在做實際工作,但Facade模式本身也必須將它的接口轉換成子系統的接口,這裡是不是有點適配器模式的感覺呢?這就是學習結構型設計模式的感覺,感覺都很相似,但是仔細的去研究時,就會發現各自的用處。
這裡實現的代碼就是參照我上面舉的編譯器的例子。
/*
** FileName : FacadePatternDemo
** Author : Jelly Young
** Date : 2014/1/2
** Description : More information, please go to http://www.jellythink.com
*/#include <iostream>using namespace std;// 語法分析子系統class CSyntaxParser{public:
void SyntaxParser()
{
cout<<"Syntax Parser"<<endl;
}};// 生成中間代碼子系統class CGenMidCode{public:
void GenMidCode()
{
cout<<"Generate middle code"<<endl;
}};// 生成匯編代碼子系統class CGenAssemblyCode{public:
void GenAssemblyCode()
{
cout<<"Generate assembly code"<<endl;
}};// 鏈接生成可執行應用程序或庫子系統class CLinkSystem{public:
void LinkSystem()
{
cout<<"Link System"<<endl;
}};class Facade{public:
void Compile()
{
CSyntaxParser syntaxParser;
CGenMidCode genMidCode;
CGenAssemblyCode genAssemblyCode;
CLinkSystem linkSystem;
syntaxParser.SyntaxParser();
genMidCode.GenMidCode();
genAssemblyCode.GenAssemblyCode();
linkSystem.LinkSystem();
}};// 客戶端int main(){
Facade facade;
facade.Compile();}
上面的代碼很簡單。我們可以想象,如果沒有使用外觀模式,在客戶端如果要進行Compile同樣的動作時,就需要寫一堆和Compile中一樣的代碼;是的,你會說,寫就寫吧。但是,有的時候,客戶端並不會非常熟悉子系統之間的關系,就好比,先要進行語法分析,再生成中間代碼,然後生成匯編語言,最後進行鏈接一樣。如果客戶端不知道這個時序,那怎麼辦?所以,外觀模式讓一切復雜的東西,使用起來都變的簡單了。
外觀模式簡單易用,讓客戶能更簡單的去使用子系統;在拜讀別人的文章時,有以下總結非常好,我也借鑒一下:
通常來講,對於子系統的訪問,我們提供一個Facade層,而這個Facade入口,只需要一個;也就是說在使用Facade時,我們可以使用單例模式來實現Facade模式。對於外觀模式到此就總結完成了,肯定有一些地方遺漏了,請大家指正。我堅信,分享使我們更加進步。