2. 橋接模式
2.1. 模式動機
設(shè)想如果要繪制矩形、圓形、橢圓、正方形,我們至少需要4個形狀類,但是如果繪制的圖形需要具有不同的顏色,如紅色、綠色、藍(lán)色等,此時至少有如下兩種設(shè)計方案:
第一種設(shè)計方案是為每一種形狀都提供一套各種顏色的版本。
第二種設(shè)計方案是根據(jù)實際需要對形狀和顏色進行組合
對于有兩個變化維度(即兩個變化的原因)的系統(tǒng),采用方案二來進行設(shè)計系統(tǒng)中類的個數(shù)更少,且系統(tǒng)擴展更為方便。設(shè)計方案二即是橋接模式的應(yīng)用。橋接模式將繼承關(guān)系轉(zhuǎn)換為關(guān)聯(lián)關(guān)系,從而降低了類與類之間的耦合,減少了代碼編寫量。
2.2. 模式定義
橋接模式(Bridge Pattern):將抽象部分與它的實現(xiàn)部分分離,使它們都可以獨立地變化。它是一種對象結(jié)構(gòu)型模式,又稱為柄體(Handle and Body)模式或接口(Interface)模式。
2.3. 模式結(jié)構(gòu)
橋接模式包含如下角色:
Abstraction:抽象類
RefinedAbstraction:擴充抽象類
Implementor:實現(xiàn)類接口
ConcreteImplementor:具體實現(xiàn)類

2.4. 時序圖

2.5. 代碼分析
#include <iostream>
#include "ConcreteImplementorA.h"
#include "ConcreteImplementorB.h"
#include "RefinedAbstraction.h"
#include "Abstraction.h"
using namespace std;
int main(int argc, char *argv[])
{
Implementor * pImp = new ConcreteImplementorA();
Abstraction * pa = new RefinedAbstraction(pImp);
pa->operation();
Abstraction * pb = new RefinedAbstraction(new ConcreteImplementorB());
pb->operation();
delete pa;
delete pb;
return 0;
}
///
// RefinedAbstraction.h
// Implementation of the Class RefinedAbstraction
// Created on: 03-十月-2014 18:12:43
// Original author: colin
///
#if !defined(EA_4BA5BE7C_DED5_4236_8362_F2988921CFA7__INCLUDED_)
#define EA_4BA5BE7C_DED5_4236_8362_F2988921CFA7__INCLUDED_
#include "Abstraction.h"
class RefinedAbstraction : public Abstraction
{
public:
RefinedAbstraction();
RefinedAbstraction(Implementor* imp);
virtual ~RefinedAbstraction();
virtual void operation();
};
#endif // !defined(EA_4BA5BE7C_DED5_4236_8362_F2988921CFA7__INCLUDED_)
///
// RefinedAbstraction.cpp
// Implementation of the Class RefinedAbstraction
// Created on: 03-十月-2014 18:12:43
// Original author: colin
///
#include "RefinedAbstraction.h"
#include <iostream>
using namespace std;
RefinedAbstraction::RefinedAbstraction(){
}
RefinedAbstraction::RefinedAbstraction(Implementor* imp)
:Abstraction(imp)
{
}
RefinedAbstraction::~RefinedAbstraction(){
}
void RefinedAbstraction::operation(){
cout << "do something else ,and then " << endl;
m_pImp->operationImp();
}
運行結(jié)果:

2.6. 模式分析
理解橋接模式,重點需要理解如何將抽象化(Abstraction)與實現(xiàn)化(Implementation)脫耦,使得二者可以獨立地變化。
抽象化:抽象化就是忽略一些信息,把不同的實體當(dāng)作同樣的實體對待。在面向?qū)ο笾?,將對象的共同性質(zhì)抽取出來形成類的過程即為抽象化的過程。
實現(xiàn)化:針對抽象化給出的具體實現(xiàn),就是實現(xiàn)化,抽象化與實現(xiàn)化是一對互逆的概念,實現(xiàn)化產(chǎn)生的對象比抽象化更具體,是對抽象化事物的進一步具體化的產(chǎn)物。
脫耦:脫耦就是將抽象化和實現(xiàn)化之間的耦合解脫開,或者說是將它們之間的強關(guān)聯(lián)改換成弱關(guān)聯(lián),將兩個角色之間的繼承關(guān)系改為關(guān)聯(lián)關(guān)系。橋接模式中的所謂脫耦,就是指在一個軟件系統(tǒng)的抽象化和實現(xiàn)化之間使用關(guān)聯(lián)關(guān)系(組合或者聚合關(guān)系)而不是繼承關(guān)系,從而使兩者可以相對獨立地變化,這就是橋接模式的用意。
2.7. 實例
如果需要開發(fā)一個跨平臺視頻播放器,可以在不同操作系統(tǒng)平臺(如Windows、Linux、Unix等)上播放多種格式的視頻文件,常見的視頻格式包括MPEG、RMVB、AVI、WMV等?,F(xiàn)使用橋接模式設(shè)計該播放器。
2.8. 優(yōu)點
橋接模式的優(yōu)點:
分離抽象接口及其實現(xiàn)部分。
橋接模式有時類似于多繼承方案,但是多繼承方案違背了類的單一職責(zé)原則(即一個類只有一個變化的原因),復(fù)用性比較差,而且多繼承結(jié)構(gòu)中類的個數(shù)非常龐大,橋接模式是比多繼承方案更好的解決方法。
橋接模式提高了系統(tǒng)的可擴充性,在兩個變化維度中任意擴展一個維度,都不需要修改原有系統(tǒng)。
實現(xiàn)細(xì)節(jié)對客戶透明,可以對用戶隱藏實現(xiàn)細(xì)節(jié)。
2.9. 缺點
橋接模式的缺點:
橋接模式的引入會增加系統(tǒng)的理解與設(shè)計難度,由于聚合關(guān)聯(lián)關(guān)系建立在抽象層,要求開發(fā)者針對抽象進行設(shè)計與編程。
橋接模式要求正確識別出系統(tǒng)中兩個獨立變化的維度,因此其使用范圍具有一定的局限性。
2.10. 適用環(huán)境
在以下情況下可以使用橋接模式:
如果一個系統(tǒng)需要在構(gòu)件的抽象化角色和具體化角色之間增加更多的靈活性,避免在兩個層次之間建立靜態(tài)的繼承聯(lián)系,通過橋接模式可以使它們在抽象層建立一個關(guān)聯(lián)關(guān)系。
抽象化角色和實現(xiàn)化角色可以以繼承的方式獨立擴展而互不影響,在程序運行時可以動態(tài)將一個抽象化子類的對象和一個實現(xiàn)化子類的對象進行組合,即系統(tǒng)需要對抽象化角色和實現(xiàn)化角色進行動態(tài)耦合。
一個類存在兩個獨立變化的維度,且這兩個維度都需要進行擴展。
雖然在系統(tǒng)中使用繼承是沒有問題的,但是由于抽象化角色和具體化角色需要獨立變化,設(shè)計要求需要獨立管理這兩者。
對于那些不希望使用繼承或因為多層次繼承導(dǎo)致系統(tǒng)類的個數(shù)急劇增加的系統(tǒng),橋接模式尤為適用。
2.11. 模式應(yīng)用
一個Java桌面軟件總是帶有所在操作系統(tǒng)的視感(LookAndFeel),如果一個Java軟件是在Unix系統(tǒng)上開發(fā)的,那么開發(fā)人員看到的是Motif用戶界面的視感;在Windows上面使用這個系統(tǒng)的用戶看到的是Windows用戶界面的視感;而一個在Macintosh上面使用的用戶看到的則是Macintosh用戶界面的視感,Java語言是通過所謂的Peer架構(gòu)做到這一點的。Java為AWT中的每一個GUI構(gòu)件都提供了一個Peer構(gòu)件,在AWT中的Peer架構(gòu)就使用了橋接模式
2.12. 模式擴展
適配器模式與橋接模式的聯(lián)用:
橋接模式和適配器模式用于設(shè)計的不同階段,橋接模式用于系統(tǒng)的初步設(shè)計,對于存在兩個獨立變化維度的類可以將其分為抽象化和實現(xiàn)化兩個角色,使它們可以分別進行變化;而在初步設(shè)計完成之后,當(dāng)發(fā)現(xiàn)系統(tǒng)與已有類無法協(xié)同工作時,可以采用適配器模式。但有時候在設(shè)計初期也需要考慮適配器模式,特別是那些涉及到大量第三方應(yīng)用接口的情況。
2.13. 總結(jié)
橋接模式將抽象部分與它的實現(xiàn)部分分離,使它們都可以獨立地變化。它是一種對象結(jié)構(gòu)型模式,又稱為柄體(Handle and Body)模式或接口(Interface)模式。
橋接模式包含如下四個角色:抽象類中定義了一個實現(xiàn)類接口類型的對象并可以維護該對象;擴充抽象類擴充由抽象類定義的接口,它實現(xiàn)了在抽象類中定義的抽象業(yè)務(wù)方法,在擴充抽象類中可以調(diào)用在實現(xiàn)類接口中定義的業(yè)務(wù)方法;實現(xiàn)類接口定義了實現(xiàn)類的接口,實現(xiàn)類接口僅提供基本操作,而抽象類定義的接口可能會做更多更復(fù)雜的操作;具體實現(xiàn)類實現(xiàn)了實現(xiàn)類接口并且具體實現(xiàn)它,在不同的具體實現(xiàn)類中提供基本操作的不同實現(xiàn),在程序運行時,具體實現(xiàn)類對象將替換其父類對象,提供給客戶端具體的業(yè)務(wù)操作方法。
在橋接模式中,抽象化(Abstraction)與實現(xiàn)化(Implementation)脫耦,它們可以沿著各自的維度獨立變化。
橋接模式的主要優(yōu)點是分離抽象接口及其實現(xiàn)部分,是比多繼承方案更好的解決方法,橋接模式還提高了系統(tǒng)的可擴充性,在兩個變化維度中任意擴展一個維度,都不需要修改原有系統(tǒng),實現(xiàn)細(xì)節(jié)對客戶透明,可以對用戶隱藏實現(xiàn)細(xì)節(jié);其主要缺點是增加系統(tǒng)的理解與設(shè)計難度,且識別出系統(tǒng)中兩個獨立變化的維度并不是一件容易的事情。
橋接模式適用情況包括:需要在構(gòu)件的抽象化角色和具體化角色之間增加更多的靈活性,避免在兩個層次之間建立靜態(tài)的繼承聯(lián)系;抽象化角色和實現(xiàn)化角色可以以繼承的方式獨立擴展而互不影響;一個類存在兩個獨立變化的維度,且這兩個維度都需要進行擴展;設(shè)計要求需要獨立管理抽象化角色和具體化角色;不希望使用繼承或因為多層次繼承導(dǎo)致系統(tǒng)類的個數(shù)急劇增加的系統(tǒng)。
[上一節(jié)]設(shè)計模式-結(jié)構(gòu)型模式之適配器模式(Adapter)文章來源:http://www.zghlxwxcb.cn/news/detail-417560.html
[下一節(jié)]設(shè)計模式-結(jié)構(gòu)型模式之裝飾模式文章來源地址http://www.zghlxwxcb.cn/news/detail-417560.html
到了這里,關(guān)于設(shè)計模式-結(jié)構(gòu)型模式之橋接模式的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!