原文地址:http://www.jellythink.com/archives/132ios
如今要去畫一個圖形,圖形有長方形、圓形和扇形等等;而圖形又能夠加上不一樣的顏色,而後,咱們就能夠畫出紅色的長方形,綠色的長方形;紅色的圓形,綠色的圓形等等。而這種圖形的形狀在變化,圖形的顏色也在變化,當使用代碼去實現時,如何面對這種多方面的變化呢?這就要說到今天的橋接模式了。設計模式
對於上述的圖形與顏色的問題時,不少時候,咱們讓各個圖形類繼承顏色類,好比:ide
1 class CShape 2 { 3 }; 4 class CRectangle : public CShape 5 { 6 }; 7 class CCircle : public CShape 8 { 9 }; 10 class CColor 11 { 12 }; 13 class CRed : public CColor 14 { 15 }; 16 class CBlue : public CColor 17 { 18 }; 19 class CRedRectangle : public CRed 20 { 21 }; 22 class CBlueRectangle : public CBlue 23 { 24 };
每當咱們增長一個新的圖形,或者增長一種新的顏色時,對應的類就會以相乘的速度進行增長。當系統中的類變的多時,對應的管理也就變的複雜,這不是咱們但願看到的。同時,咱們能夠看到CRedRectangle類繼承自CRed類,這種繼承關係合理嗎?且不說有的系統是如此實現的,紅色的矩形是紅色嗎?很顯然,CRedRectangle和CRed之間不是一種is-a的關係,因此,上面的實現是及其不合理的。那麼它們是什麼關係呢?接着往下看。網站
在GOF的《設計模式:可複用面向對象軟件的基礎》一書中對橋接模式是這樣說的:將抽象部分和它的實現部分分離,使它們均可以獨立的變化。簡單粗暴的說,就是抽象對外提供調用的接口;對外隱瞞實現部分,在抽象中引用實現部分,從而實現抽象對實現部分的調用,而抽象中引用的實現部分能夠在從此的開發過程當中,切換成別的實現部分。spa
當一個抽象可能有多個實現時,一般用繼承來協調它們。抽象類定義對該抽象的接口,而具體的子類則用不一樣方式加以實現。可是此方法有時不夠靈活。繼承機制將抽象部分與它的實現部分固定在一塊兒,使得難以對抽象部分和實現部分獨立的進行修改、擴充和重用。橋接模式把依賴具體實現,提高爲依賴抽象,來完成對象和變化因素之間的低耦合,提升系統的可維護性和擴展性。橋接模式的主要目的是將一個對象的變化與其它變化隔離開,讓彼此之間的耦合度最低。設計
上面使用的場景,是一種建議,也是一種參考。在項目中要很好的把握一個設計模式,是有必定的難度的;當在實際項目中遇到知足上面的一點或者幾點時,能夠考慮使用橋接模式。指針
Abstraction類定義了抽象類的接口,而且維護一個指向Implementor實現類的指針;code
RefineAbstraction類擴充了Abstraction類的接口;orm
Implementor類定義了實現類的接口,這個接口不必定要與Abstraction的接口徹底一致;實際上,這兩個接口能夠徹底不一樣;對象
ConcreteImplementor類實現了Implementor定義的接口。
1 /* 2 ** FileName : BridgePatternDemo 3 ** Author : Jelly Young 4 ** Date : 2013/12/4 5 ** Description : More information, please go to http://www.jellythink.com 6 */ 7 #include <iostream> 8 using namespace std; 9 class Implementor 10 { 11 public: 12 virtual void OperationImpl() = 0; 13 }; 14 class ConcreteImpementor : public Implementor 15 { 16 public: 17 void OperationImpl() 18 { 19 cout<<"OperationImpl"<<endl; 20 } 21 }; 22 class Abstraction 23 { 24 public: 25 Abstraction(Implementor *pImpl) : m_pImpl(pImpl){} 26 virtual void Operation() = 0; 27 protected: 28 Implementor *m_pImpl; 29 }; 30 class RedfinedAbstraction : public Abstraction 31 { 32 public: 33 RedfinedAbstraction(Implementor *pImpl) : Abstraction(pImpl){} 34 void Operation() 35 { 36 m_pImpl->OperationImpl(); 37 } 38 }; 39 int main(int argc, char *argv[]) 40 { 41 Implementor *pImplObj = new ConcreteImpementor(); 42 Abstraction *pAbsObj = new RedfinedAbstraction(pImplObj); 43 pAbsObj->Operation(); 44 delete pImplObj; 45 pImplObj = NULL; 46 delete pAbsObj; 47 pAbsObj = NULL; 48 return 0; 49 }
根據對代碼的理解,能想象到CRedRectangle和CRed是什麼關係嗎?咱們能夠理解爲紅色的矩形包含紅色,也就是包含的關係,也就是軟件設計中的組合關係(has-a)。
這是一個我經歷的項目,也是作起來比較輕鬆的一個項目。項目是這樣的,須要對一箇中間的通訊庫進行改寫,保留之前的通訊方式的同時,須要使用一種新的通訊協議去和底層模塊進行通訊。現有的代碼是一個COM程序,向外提供了能夠調用的接口。根據客戶提供的源碼,咱們進行了分析;在分析以前,咱們有一種擔憂,就是怕用戶的代碼是接口和實現混在一塊兒的;可是,分析以後,讓咱們很吃驚,客戶的代碼結構很清晰,層次很是清楚,代碼中使用的就是咱們今天這裏說的橋接模式。因爲抽象的接口和實現徹底進行了分離,咱們在進行重寫時,只須要實現咱們的一個類,而後在接口中引用咱們實現的類,就大功告成了,這樣作到了客戶端不須要作任何修改,就能夠完美的替換掉原來的通訊層,真的是前人栽樹樹,後人乘涼啊。
橋接模式使得抽象和實現進行了分離,抽象不用依賴於實現,讓抽象和實現部分各自修改起來都很方便,使用組合(就是Abstraction類中包含了Implementor)的方式,下降了耦合度,同時也有助於分層,從而產生更好的結構化系統。經過實際的項目經驗,使用了橋接模式的代碼,對之後的擴展有很大的幫助。