結構型模式(Structural Pattern)描述如何將類或者對象結合在一塊兒造成更大的結構,就像搭積木,能夠經過簡單積木的組合造成複雜的、功能更爲強大的結構。ios
結構型模式能夠分爲類結構型模式和對象結構型模式:編程
類結構型模式關心類的組合,由多個類能夠組合成一個更大的系統,在類結構型模式中通常只存在繼承關係和實現關係。app
對象結構型模式關心類與對象的組合,經過關聯關係使得在一個類中定義另外一個類的實例對象,而後經過該對象調用其方法。編程語言
根據「合成複用原則」,在系統中儘可能使用關聯關係來替代繼承關係,所以大部分結構型模式都是對象結構型模式。一共有如下幾種模式:函數
適配器模式(Adapter) 重要程度:4spa
橋接模式(Bridge) 重要程度:4代理
組合模式(Composite) 重要程度:4code
裝飾模式(Decorator) 重要程度:3對象
外觀模式(Facade) 重要程度:5繼承
享元模式(Flyweight) 重要程度:1
代理模式(Proxy) 重要程度:4
買筆記本電腦,買手機時,都有一個電源適配器,電源適配器又叫外置電源,是小型便攜式電子設備及電子電器的供電電壓變換設備,常見於手機,筆記本電腦上。它的做用是將家裏的220V高電壓轉換成這些電子產品能工做的5V~20V左右穩定的低電壓,使它們能正常工做。就是說,若是沒有這個電源適配器,咱們的手機和電腦就不能進行充電了。
一般狀況下,客戶端能夠經過目標類的接口訪問它所提供的服務。有時,現有的類能夠知足客戶類的功能須要,可是它所提供的接口不必定是客戶類所指望的,這多是由於現有類中方法名與目標類中定義的方法名不一致等緣由所致使的。在這種狀況下,現有的接口須要轉化爲客戶類指望的接口,這樣保證了對現有類的重用。若是不進行這樣的轉化,客戶類就不能利用現有類所提供的功能,適配器模式能夠完成這樣的轉化。
在適配器模式中能夠定義一個包裝類,包裝不兼容接口的對象,這個包裝類指的就是適配器(Adapter),它所包裝的對象就是適配者(Adaptee),即被適配的類。適配器提供客戶類須要的接口,適配器的實現就是把客戶類的請求轉化爲對適配者的相應接口的調用。也就是說:當客戶類調用適配器的方法時,在適配器類的內部將調用適配者類的方法,而這個過程對客戶類是透明的,客戶類並不直接訪問適配者類。所以,適配器可使因爲接口不兼容而不能交互的類能夠一塊兒工做。
適配器模式(Adapter Pattern) :將一個接口轉換成客戶但願的另外一個接口,使接口不兼容而不能一塊兒工做的那些類能夠一塊兒工做,別名爲包裝器(Wrapper)。
Target:目標抽象類
Adapter:適配器類
Adaptee:適配者類
Client:客戶類
對象適配器
適配器Adapter類繼承自Target類,同時,在Adapter類中有一個Adaptee類型的成員變量;Adapter類重寫Request函數時,在Request中,使用Adaptee類型的成員變量調用Adaptee的SpecificRequest函數,最終完成適配。
類適配器
適配器Adapter繼承自Target和Adaptee類,Adapter類須要重寫Target類的Request函數,在Request中作適當的處理,調用Adaptee類的SepcificRequest。最終,Target實際調用的是Adaptee的SpecificRequest來完成Request的,完成適配。
類適配器有如下特色:
因爲Adapter直接繼承自Adaptee類,因此,在Adapter類中能夠對Adaptee類的方法進行重定義;
若是在Adaptee中添加了一個抽象方法,那麼Adapter也要進行相應的改動,這樣就帶來高耦合;
若是Adaptee還有其它子類,而在Adapter中想調用Adaptee其它子類的方法時,使用類適配器是沒法作到的。
對象適配器有如下特色:
有的時候,你會發現,不是很容易去構造一個Adaptee類型的對象;
當Adaptee中添加新的抽象方法時,Adapter類不須要作任何調整,也能正確的進行動做;
可使用多態的方式在Adapter類中調用Adaptee類子類的方法。
因爲對象適配器的耦合度比較低,因此在不少的書中都建議使用對象適配器。
類適配器
#include <iostream> using namespace std; // Targets class Target { public: virtual void Request() { cout << "Target::Request" << endl; } }; // Adaptee class Adaptee { public: void SpecificRequest() { cout << "Adaptee::SpecificRequest" << endl; } }; // Adapter class Adapter : public Target, Adaptee { public: void Request() { SpecificRequest(); } }; // Client int main() { Target *targetObj = new Adapter(); targetObj->Request(); delete targetObj; targetObj = NULL; system("pause"); return 0; }
對象適配器
#include <iostream> using namespace std; class Target { public: Target(){} virtual ~Target(){} virtual void Request() { cout << "Target::Request" << endl; } }; class Adaptee { public: void SpecificRequest() { cout << "Adaptee::SpecificRequest" << endl; } }; class Adapter : public Target { public: Adapter() : m_Adaptee(new Adaptee) {} ~Adapter() { if (m_Adaptee != NULL) { delete m_Adaptee; m_Adaptee = NULL; } } void Request() { m_Adaptee->SpecificRequest();//動態綁定能夠實現多態來調用adaptee子類的方法 } private: Adaptee *m_Adaptee; }; int main() { Target *targetObj = new Adapter(); targetObj->Request(); delete targetObj; targetObj = NULL; system("pause"); return 0; }
將目標類和適配者類解耦,經過引入一個適配器類來重用現有的適配者類,而無須修改原有代碼。
增長了類的透明性和複用性,將具體的實現封裝在適配者類中,對於客戶端類來講是透明的,並且提升了適配者的複用性。
靈活性和擴展性都很是好,經過使用配置文件,能夠很方便地更換適配器,也能夠在不修改原有代碼的基礎上增長新的適配器類,徹底符合「開閉原則」。
類適配器模式還具備以下優勢:
因爲適配器類是適配者類的子類,所以能夠在適配器類中置換一些適配者的方法,使得適配器的靈活性更強。
對象適配器模式還具備以下優勢:
一個對象適配器能夠把多個不一樣的適配者適配到同一個目標,也就是說,同一個適配器能夠把適配者類和它的子類都適配到目標接口。
類適配器模式的缺點以下:
對於Java、C#等不支持多重繼承的語言,一次最多隻能適配一個適配者類,並且目標抽象類只能爲抽象類,不能爲具體類,其使用有必定的侷限性,不能將一個適配者類和它的子類都適配到目標接口。
對象適配器模式的缺點以下:
與類適配器模式相比,要想置換適配者類的方法就不容易。若是必定要置換掉適配者類的一個或多個方法,就只好先作一個適配者類的子類,將適配者類的方法置換掉,而後再把適配者類的子類當作真正的適配者進行適配,實現過程較爲複雜。
系統須要使用現有的類,而這些類的接口不符合系統的須要。
想要創建一個能夠重複使用的類,用於與一些彼此之間沒有太大關聯的一些類,包括一些可能在未來引進的類一塊兒工做。
結構型模式描述如何將類或者對象結合在一塊兒造成更大的結構。
適配器模式用於將一個接口轉換成客戶但願的另外一個接口,適配器模式使接口不兼容的那些類能夠一塊兒工做,其別名爲包裝器。適配器模式既能夠做爲類結構型模式,也能夠做爲對象結構型模式。
適配器模式包含四個角色:目標抽象類定義客戶要用的特定領域的接口;適配器類能夠調用另外一個接口,做爲一個轉換器,對適配者和抽象目標類進行適配,它是適配器模式的核心;適配者類是被適配的角色,它定義了一個已經存在的接口,這個接口須要適配;在客戶類中針對目標抽象類進行編程,調用在目標抽象類中定義的業務方法。
在類適配器模式中,適配器類實現了目標抽象類接口並繼承了適配者類,並在目標抽象類的實現方法中調用所繼承的適配者類的方法;在對象適配器模式中,適配器類繼承了目標抽象類並定義了一個適配者類的對象實例,在所繼承的目標抽象類方法中調用適配者類的相應業務方法。
適配器模式的主要優勢是將目標類和適配者類解耦,增長了類的透明性和複用性,同時系統的靈活性和擴展性都很是好,更換適配器或者增長新的適配器都很是方便,符合「開閉原則」;類適配器模式的缺點是適配器類在不少編程語言中不能同時適配多個適配者類,對象適配器模式的缺點是很難置換適配者類的方法。
適配器模式適用狀況包括:系統須要使用現有的類,而這些類的接口不符合系統的須要;想要創建一個能夠重複使用的類,用於與一些彼此之間沒有太大關聯的一些類一塊兒工做。