Abstract
facade是我學到的第三個pattern,也是個很簡單的pattern,主要是將眾多class重新包裝成一個更好用的class。Intent替子系統裡的一堆介面定義一套統一的高階介面,讓子系統更易使用。Introduction Facade常用在兩個地方,第一種用法是將原來程序導向的系統,利用Facade包成OO,如MFC包裝Win32 API,第二種用法是將原來複雜的OO系統,再包成更簡單的OO,如.NET Enterprise Library將.NET Framework再做一次包裝,讓你更容易使用.NET。另外3-tier也是典型Facade的應用,DAL(Data Access Layer)就是一個Facade,讓BLL(Business Logic Layer)在存取資料時,不用對付ADO.NET複雜的機制,只需面對DAL即可。Sample Code如我們坐捷運買票,目前的賣票的機器只能吃銅板,所以得另外的提供換鈔機,讓旅客將紙幣換成銅板,也就是說,若一個旅客身上只有紙幣又要賣捷運票,他必須做兩個步驟,先將紙幣換成銅板,再用銅板去買車票。 1 /**/ /* 2(C) OOMusou 2007 http://oomusou.cnblogs.com 3 4Filename : DP_FacadePattern1_before.cpp 5Compiler : Visual C++ 8.0 / BCB 6.0 / gcc 3.4.2 / ISO C++ 6Description : Demo how to use Facade pattern (before) 7Release : 04/24/2007 1.0 8*/ 9 #include < iostream > 10 11 using namespace std; 12 13 struct Bill { 14 int value;15 Bill(int value) : value(value) {}16} ; 17 18 struct Coin { 19 int value;20 Coin(int value) : value(value) {}21} ; 22 23 class BillToCoinMachine { 24public:25 Coin getCoin(Bill bill) { 26 return Coin(10);27 }28} ; 29 30 class CoinToTicketMachine { 31public:32 void getTicket(Coin coin) { 33 cout << "Get ticket" << endl;34 }35} ; 36 37 int main() { 38 BillToCoinMachine machine1;39 Coin coin = machine1.getCoin(Bill(100));40 41 CoinToTicketMachine machine2;42 machine2.getTicket(coin);43}
執行結果 Get ticket
但對於旅客來說,似乎太嫌麻煩,買個票要排兩次隊,若我們能設計一部機器,能吃紙鈔,且能購票,那對旅客將非常的方便。事實上,我們並不需重新設計這樣的機器,只要將這兩台機器整合成一台即可。 1 /**/ /* 2(C) OOMusou 2007 http://oomusou.cnblogs.com 3 4Filename : DP_FacadePattern1_after.cpp 5Compiler : Visual C++ 8.0 / BCB 6.0 / gcc 3.4.2 / ISO C++ 6Description : Demo how to use Facade pattern (after) 7Release : 04/24/2007 1.0 8*/ 9 #include < iostream > 10 11 using namespace std; 12 13 struct Bill { 14 int value;15 Bill(int value) : value(value) {}16} ; 17 18 struct Coin { 19 int value;20 Coin(int value) : value(value) {}21} ; 22 23 class BillToCoinMachine { 24public:25 Coin getCoin(Bill bill) { 26 return Coin(10);27 }28} ; 29 30 class CoinToTicketMachine { 31public:32 void getTicket(Coin coin) { 33 cout << "Get ticket" << endl;34 }35} ; 36 37 class TicketMachineFacade { 38public:39 void coinToTicket(Coin coin) { 40 CoinToTicketMachine machine;41 machine.getTicket(coin);42 }43 44 void billToTicket(Bill bill) { 45 BillToCoinMachine machine1;46 Coin coin = machine1.getCoin(bill);47 48 CoinToTicketMachine machine2;49 machine2.getTicket(coin);50 }51} ; 52 53 int main() { 54 TicketMachineFacade TMFacade;55 TMFacade.billToTicket(Bill(100));56 TMFacade.coinToTicket(Coin(10));57}
執行結果 1 Get ticket 2 Get ticket
可以看到client的程式明顯乾淨多了 int main() { TicketMachineFacade TMFacade; TMFacade.billToTicket(Bill(100)); TMFacade.coinToTicket(Coin(10));}
這表示旅客可以用更簡單的方式買票了。Consequence1.避免外界觸及子系統的元件,降低外界所要面對的物件數量,讓子系統更容易使用。 2.促成外界與子系統之間的低偶合性。在子系統裡,元件之間的耦合性往往都很高,降低耦合性會使原件更容易改變而不波及外界。Facade有助於將系統分層、將物件之間的依存關係分層,順便剔除複雜的、循環的依存關係;這對於需要將client和子系統分開製作的專案而言,是非常重要的性質。 對大型軟體系統來說,降低編譯方面的依存關係是非常重要的;子系統一有變動,大家都希望重新編譯的時間能越短越好。只要用Facade降低編譯依存關係,不僅能將重新編譯的動作侷限在一小塊區域,更有利於軟體移植:只是重新編譯一塊子系統,不太需要其他地方也一起再編譯一遍。 3.如有必要,外界仍可直接接觸子系統內的類別,所以你可以在易用性與一般性之間做選擇。Conclusion或許你會覺得facade pattern沒什麼,的確,他只是一個概念而已,而且非常單純,但卻常常看的到。Known use1..NET Enterprise Library的DAAB 2..NET 2.0的My 3.網路架構的OSI模型 See Also
Reference
GoF,Design Patterns,Addison Weseley ,1995