橋接模式及C++實現


橋接模式

先說說橋接模式的定義:將抽象化(Abstraction)與實現化(Implementation)分離,使得二者可以獨立地變化。

橋接模式號稱設計模式中最難理解的模式之一,關鍵就是這個抽象和實現的分離非常讓人奇怪,大部分人剛看到這個定義的時候都會認為實現就是繼承自抽象,那怎么可能將他們分離呢。

這里引用《大話設計模式》里面的那個例子。這個例子中,每次添加一個新的手機品牌,則必須要添加相應的通訊錄和游戲,而每次要給每個手機添加新功能,則所有的手機品牌下都必須繼承一個新的類,這樣工作量就大了,而且可能通訊錄和游戲的實現方法是一樣的,這就有很多重復代碼。看到這里可能已經看到了端倪了,雖然這個最頂層的抽象手機品牌一般是固定不變的,但是下面的各個繼承類手機品牌M和手機品牌N卻是時常會發生變化的。而只要手機品牌M和手機品牌N發生變化,它下面的繼承類也要發生變化,這樣極大的增加了代碼的耦合性,加入通訊錄和游戲下面還繼續繼承有類的話,那耦合性就更強了,改起來基本就是噩夢了。

其實也可以這樣看,雖然手機品牌M和手機品牌N這兩個類是有一部分抽象,但是還沒有達到完全的抽象,還是會發生變化的。

所以,其實定義里說的實現是指的最下層的那些具體實現,抽象是指的他的父類或者更上層的父類,而要將抽象和實現分離,就是分離這個抽象和實現。說的通俗點,就是不要繼承的太多了,最好是就繼承一層。(我自己的理解)所以才有了合成/聚合復用原則。

合成/聚合復用原則:盡量使用合成/聚合,盡量不要使用類繼承。我對這句話的理解就是,不要繼承太多了,如果需要太多繼承,可以考慮改為合成/聚合。

 

image

下面可以看看橋接模式的具體類圖了。橋接模式就將實現與抽象分離開來,使得RefinedAbstraction依賴於抽象的實現,這樣實現了依賴倒轉原則,而不管左邊的抽象如何變化,只要實現方法不變,右邊的具體實現就不需要修改,而右邊的具體實現方法發生變化,只要接口不變,左邊的抽象也不需要修改。

說起來,其實橋接模式倒是與抽象工廠模式有點像,可以回憶一下抽象工廠模式,抽象工廠模式也是解決多種因素變化的一種方式,抽象工廠模式中,產品的種類和產品的具體實現都會發生變化,於是將產品的種類抽象出來,將具體的實現隔離開來。

image

 

最新體會:有一種情況,你事先定義了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

 

運行結果

image


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM