橋接模式
先說說橋接模式的定義:將抽象化(Abstraction)與實現化(Implementation)分離,使得二者可以獨立地變化。
橋接模式號稱設計模式中最難理解的模式之一,關鍵就是這個抽象和實現的分離非常讓人奇怪,大部分人剛看到這個定義的時候都會認為實現就是繼承自抽象,那怎么可能將他們分離呢。
這里引用《大話設計模式》里面的那個例子。這個例子中,每次添加一個新的手機品牌,則必須要添加相應的通訊錄和游戲,而每次要給每個手機添加新功能,則所有的手機品牌下都必須繼承一個新的類,這樣工作量就大了,而且可能通訊錄和游戲的實現方法是一樣的,這就有很多重復代碼。看到這里可能已經看到了端倪了,雖然這個最頂層的抽象手機品牌一般是固定不變的,但是下面的各個繼承類手機品牌M和手機品牌N卻是時常會發生變化的。而只要手機品牌M和手機品牌N發生變化,它下面的繼承類也要發生變化,這樣極大的增加了代碼的耦合性,加入通訊錄和游戲下面還繼續繼承有類的話,那耦合性就更強了,改起來基本就是噩夢了。
其實也可以這樣看,雖然手機品牌M和手機品牌N這兩個類是有一部分抽象,但是還沒有達到完全的抽象,還是會發生變化的。
所以,其實定義里說的實現是指的最下層的那些具體實現,抽象是指的他的父類或者更上層的父類,而要將抽象和實現分離,就是分離這個抽象和實現。說的通俗點,就是不要繼承的太多了,最好是就繼承一層。(我自己的理解)所以才有了合成/聚合復用原則。
合成/聚合復用原則:盡量使用合成/聚合,盡量不要使用類繼承。我對這句話的理解就是,不要繼承太多了,如果需要太多繼承,可以考慮改為合成/聚合。
下面可以看看橋接模式的具體類圖了。橋接模式就將實現與抽象分離開來,使得RefinedAbstraction依賴於抽象的實現,這樣實現了依賴倒轉原則,而不管左邊的抽象如何變化,只要實現方法不變,右邊的具體實現就不需要修改,而右邊的具體實現方法發生變化,只要接口不變,左邊的抽象也不需要修改。
說起來,其實橋接模式倒是與抽象工廠模式有點像,可以回憶一下抽象工廠模式,抽象工廠模式也是解決多種因素變化的一種方式,抽象工廠模式中,產品的種類和產品的具體實現都會發生變化,於是將產品的種類抽象出來,將具體的實現隔離開來。
最新體會:有一種情況,你事先定義了Abstction類和RefinedAbstraction類,你的代碼中直接使用的是RefinedAbstraction類,剛開始RefinedAbstraction是夠用的。但后來你希望operation()能在不同的情況下有不同的實現,這時候原有的結構就不夠用了,你不可能重新繼承一個類,那樣所有的地方都必須修改,可以考慮的做法就是繼承RefinedAbstraction類,這樣的改動就比較少,但這樣不是最好的。最好的應該是使用上面的橋接模式,將實現分離出來,這樣所有的地方都不需要修改,只要添加它的實現就可以了。
常用的場景
1.當一個對象有多個變化因素的時候,考慮依賴於抽象的實現,而不是具體的實現。如上面例子中手機品牌有2種變化因素,一個是品牌,一個是功能。
2.當多個變化因素在多個對象間共享時,考慮將這部分變化的部分抽象出來再聚合/合成進來,如上面例子中的通訊錄和游戲,其實是可以共享的。
3.當我們考慮一個對象的多個變化因素可以動態變化的時候,考慮使用橋接模式,如上面例子中的手機品牌是變化的,手機的功能也是變化的,所以將他們分離出來,獨立的變化。
優點
1.將實現抽離出來,再實現抽象,使得對象的具體實現依賴於抽象,滿足了依賴倒轉原則。
2.將可以共享的變化部分,抽離出來,減少了代碼的重復信息。
3.對象的具體實現可以更加靈活,可以滿足多個因素變化的要求。
缺點
1.客戶必須知道選擇哪一種類型的實現。
C++實現代碼
1 #ifndef _ABSTRACTION_H_ 2 #define _ABSTRACTION_H_ 3 4 #include "AbstractionImplement.h" 5 6 class Abstraction 7 { 8 public: 9 Abstraction(); 10 virtual ~Abstraction(); 11 12 virtual void operation() = 0; 13 14 15 }; 16 17 class DefinedAbstraction: public Abstraction 18 { 19 public: 20 DefinedAbstraction(AbstractionImplement* absImp); 21 ~DefinedAbstraction(); 22 23 void operation(); 24 25 private: 26 AbstractionImplement* absImp; 27 }; 28 29 30 #endif
1 #include "Abstraction.h" 2 3 4 Abstraction::Abstraction() 5 { 6 7 } 8 9 10 11 Abstraction::~Abstraction() 12 { 13 14 } 15 16 17 DefinedAbstraction::DefinedAbstraction(AbstractionImplement* absImp) 18 { 19 this->absImp = absImp; 20 } 21 22 23 DefinedAbstraction::~DefinedAbstraction() 24 { 25 26 } 27 28 29 void DefinedAbstraction::operation() 30 { 31 absImp->operation(); 32 }
1 #ifndef _ABSTRACTIONIMPLEMENT_H_ 2 #define _ABSTRACTIONIMPLEMENT_H_ 3 4 5 class AbstractionImplement 6 { 7 public: 8 AbstractionImplement(); 9 virtual ~AbstractionImplement(); 10 11 virtual void operation() = 0; 12 }; 13 14 15 class ConcreteAbstractionImplement1:public AbstractionImplement 16 { 17 public: 18 ConcreteAbstractionImplement1(); 19 ~ConcreteAbstractionImplement1(); 20 21 void operation(); 22 }; 23 24 class ConcreteAbstractionImplement2:public AbstractionImplement 25 { 26 public: 27 ConcreteAbstractionImplement2(); 28 ~ConcreteAbstractionImplement2(); 29 30 void operation(); 31 }; 32 33 34 #endif
1 #include "AbstractionImplement.h" 2 #include <stdio.h> 3 4 5 6 AbstractionImplement::AbstractionImplement() 7 { 8 9 } 10 11 12 AbstractionImplement::~AbstractionImplement() 13 { 14 15 } 16 17 18 ConcreteAbstractionImplement1::ConcreteAbstractionImplement1() 19 { 20 21 } 22 23 24 ConcreteAbstractionImplement1::~ConcreteAbstractionImplement1() 25 { 26 27 } 28 29 30 void ConcreteAbstractionImplement1::operation() 31 { 32 fprintf(stderr, "ConcreteAbstractionImplement1\n" ); 33 } 34 35 36 ConcreteAbstractionImplement2::ConcreteAbstractionImplement2() 37 { 38 39 } 40 41 42 ConcreteAbstractionImplement2::~ConcreteAbstractionImplement2() 43 { 44 45 } 46 47 48 void ConcreteAbstractionImplement2::operation() 49 { 50 fprintf(stderr, "ConcreteAbstractionImplement2\n" ); 51 }
1 #include "Abstraction.h" 2 3 4 5 int main() 6 { 7 AbstractionImplement* absImp1 = new ConcreteAbstractionImplement1(); 8 Abstraction* abs1 = new DefinedAbstraction(absImp1); 9 10 abs1->operation(); 11 12 AbstractionImplement* absImp2 = new ConcreteAbstractionImplement2(); 13 Abstraction* abs2 = new DefinedAbstraction(absImp2); 14 15 abs2->operation(); 16 return 0; 17 }
1 g++ -o client client.cpp Abstraction.cpp AbstractionImplement.cpp
運行結果