2018-09-20 01:33:12linux
仍是用大話設計模式中的例子:股票和基金來講明外觀模式。股票買入者直接操做股票,他須要瞭解幾千只股票的各類信息還須要預測它的漲跌,這樣買入者和股票直接有着直接的聯繫,在軟件開發種,這就是高耦合(模塊和模塊之間的聯繫過多)。買入基金,則由專業的基金經理人操做用戶的資源,買入者只須要和基金經理人打交道,具體股票的細節,則由基金經理人來處理。ios
外觀模式(Facade Pattern)又稱門面模式:爲子系統中的一組接口提供一個一致的界面,此模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。設計模式
其中:SubSystemOne、SubSystemTwo、SubSystemThree、SubSystemFour 構成了一個子系統。bash
Facade:外觀類,知道哪些子系統,它們有哪些功能,通常Client把像子系統的請求委託給Facade,而後Facade再把這個請求轉給適合的子系統對象。(System和Facade實際上是聚合關係,它們之間沒有太多的耦合性)架構
SubSystem:子系統,子系統能夠同時有多個,一個系統能夠是類的集合或者是一個單獨的類。每一個子系統能夠單獨被Client調用也能夠被Facade調用,對於Client來講它不知道有Facade的存在,Facade對子系統而言就是一個Client。ide
優勢:函數
1.Client只與Facade打交道,下降了Client代碼的複雜度。spa
2.下降了Client和System的耦合度,子系統有調整時不會影響到Client或者影響較小,可以經過調整Facade來適應子系統的改變。設計
3.下降了大型軟件中的編譯依賴性,並簡化了系統在不一樣平臺之間而定移植過程,由於設計良好的子系統,通常而言是相互獨立的,一個系統的改變不會影響到其它子系統,而子系統的內部變化(指實現細節)也不會影響到外觀,因此只須要編譯有變化的子系統便可(對GCC編譯器)。code
4.模式僅提供了一個訪問子系統的統一入口,可是並不阻止用戶直接使用子系統類。
缺點:
1.不能很好地限制Client使用子系統,若是要給Client添加使用限制,將多是整個模式喪失它的靈活性,也會增長其複雜度(試想一下爲每一個子系統添加定製化的限制,在實現是將會有多複雜)
2.在不引入抽象外觀類(Facade)的狀況下,增長子系統,要對應的調整Facade和Client(考慮下簡單工廠模式),這會違背開放-封閉原則。
問題模型:假設咱們在開發一個GUI程序,經過界面咱們可以產生一組通用數據,可是這組通用數據須要被不一樣的子系統按需選擇,並進行對應的處理。好比咱們能在bash終端輸入不一樣的命令調用不一樣的處理程序。咱們假設這是一個外觀模式(但真實的應用狀況不是這樣,由於,linux下的各類命令其實是由我的開發者自行開發的程序,在使用時,bash終端輸入程序名 參數便可使用命令提供的服務)。那麼如今main函數就是客戶代碼,S1表示調用子系統S1執行某種操做,S2表示調用S2執行某種操做等等。網上有個電商的例子,我以爲比較好,它沒有我這個這麼理想化,子系統之間的數據沒有耦合。
1.3個子系統
#ifndef SUBSYSTEMA_H_ #define SUBSYSTEMA_H_ #include <iostream> class SubSystemA { public: void methodA() { std::cout << "I am SystemA!" << std::endl; } SubSystemA() = default; ~SubSystemA() = default; }; #endif
#ifndef SUBSYSTEMB_H_ #define SUBSYSTEMB_H_ #include <iostream> #include <ctime> class SubSystemB { public: void methodB() { auto systTime = time(nullptr); tm *struSysTime = localtime(&systTime); char szTime[16] = {0}; sprintf(szTime,"%04d-%02d-%02d",struSysTime->tm_year+1990,struSysTime->tm_mon+1,struSysTime->tm_mday); std::cout << "Today is:" << szTime << std::endl; } SubSystemB() = default; ~SubSystemB() = default; }; #endif
#ifndef SUBSYSTEMC_H_ #define SUBSYSTEMC_H_ #include <iostream> #include <ctime> class SubSystemC { public: void methodC() { auto systTime = time(nullptr); tm *struSysTime = localtime(&systTime); char szTime[16] = {0}; sprintf(szTime,"%02d:%02d:%02d",struSysTime->tm_hour,struSysTime->tm_min,struSysTime->tm_sec); std::cout << "Now Time is:"<< szTime << std::endl; } SubSystemC() = default; ~SubSystemC() = default; }; #endif
2.Facade外觀類,也是這個模式的核心
#ifndef FACADE_H_ #define FACADE_H_ #include "SubSystemA.h" #include "SubSystemB.h" #include "SubSystemC.h" #include <string> class Facade { public: void noteSubSystem(const std::string strParam); Facade() = default; ~Facade() = default; private: SubSystemA m_objSubSystemA; SubSystemB m_objSubSystemB; SubSystemC m_objSubSystemC; }; #endif #include "Facade.h" void Facade::noteSubSystem(const std::string strSystemName) { if(strSystemName == "SubSystemA") m_objSubSystemA.methodA(); else if(strSystemName == "SubSystemB") m_objSubSystemB.methodB(); else if(strSystemName == "SubSystemC") m_objSubSystemC.methodC(); else std::cout << "Param Error" << std::endl; }
3.客戶端代碼
#include "Facade.h" using namespace std; int main(int argc,char*argv[]) { if(argc != 2) { std::cout << "The count of param is Error!" <<std::endl; return (0); } std::string strParam = argv[1]; Facade objFacade; objFacade.noteSubSystem(strParam); return (1); }
外觀模式的使用:
1.在設計階段就要有意識的把不一樣的層分離(三層架構:數據訪問層、業務邏輯層、表示層,在層與層之間創建外觀Facade)
2.開發階段,子系統由於不斷的重構變的愈來愈複雜。增長外觀模式。能夠提供一個簡單的接口,減小它們之間的依賴
3.爲新系統開發一個外觀Facade類,來提供設計粗糙或高度負責的遺留代碼的比較清晰簡單的接口,讓新系統與Facade對象交互,Facade與遺留代碼交互全部的複雜工做。
d