定義 **橋接模式(Bridge Pattern)**定義:將抽象化與實現化分離,使得雙方可以獨立變化。 當然定義什麼的通常都晦澀難懂,咱們還是藉助例子來理解。 舉例 還是舉個例子吧。 假如說,有個圖形(Graphics)介面,具有方法draw(),他有兩個可以變化的維度,形狀(Shape)和顏色( ...
定義
橋接模式(Bridge Pattern)定義:將抽象化與實現化分離,使得雙方可以獨立變化。
當然定義什麼的通常都晦澀難懂,咱們還是藉助例子來理解。
舉例
還是舉個例子吧。
假如說,有個圖形(Graphics
)介面,具有方法draw()
,他有兩個可以變化的維度,形狀(Shape
)和顏色(Color
)。怎麼實現呢?容易想到這樣一種方式:先從Graphics
類繼承出矩形(Rectangle
)、圓形(Circle
)等形狀子類,再給每個形狀子類分別派生出紅色矩形(RedRectangle
)、綠色矩形(GreenRectangle
)、紅色圓形(RedCircle
)和綠色圓形(GreenCircle
)。
此時的類體繫結構如下:
有什麼問題?
不難發現,如果我們要新增加一個形狀,例如三角形,我們就需要對應增加n個子類(其中n=顏色個數),來使三角形具有不同的顏色。同樣,如果我們要增加一種顏色,例如黃色,那麼就需要對應增加m個子類(其中m=形狀個數),來使所有的形狀都具有黃色這種顏色。
事實上,如果我們有m種形狀,n種顏色,那麼我們一共需要的類的個數為m*n。
這也太可怕了吧!人是喜歡偷懶的動物,誰也不想為了區區幾個形狀和顏色寫這麼多個類。而且隨著形狀和顏色的增加,類的個數的增長速度也會越來越快,造成類爆炸。那有沒有一種辦法,可以讓我們不需要寫那麼多類呢?答案當然是有的!試試看用組合替代繼承會怎樣?
咱們還是從Graphics
類派生出各個形狀子類,但不同的是,這次改用組合來使形狀具有不同顏色,這時的類體繫結構如下:
看,採用組合替代繼承之後,當我們需要增加一種形狀的時候,我們是不是只需要多寫一個類了,不用為每個顏色對應增加一個形狀類。同樣,需要增加一種顏色的時候,也只需要寫一個類,不用讓每個形狀都具有這種顏色。如果我們有m種形狀,n種顏色,那麼我們就只需要m+n個類就可以了,是不是比m*n要少的多了。
那上面的例子中,每個部分都扮演著什麼樣的角色呢?
抽象化(Abstraction):如例子中的Graphics
類。
擴展抽象化(Refined Abstraction):由抽象化類派生而來,通過組合關係調用實現化類的相應方法,如例子中的Rectangle
、Circle
等類。
實現化(Implementation):如例子中的Color
類。
具體實現化(Concrete Implementation):如例子中的Red
、Green
等類。
事實上,這隻是橋接模式的其中一個使用場景。
使用場景
- 需要在抽象化和實現化角色之間增加更多的靈活性。
- 不希望因為類繼承導致類的個數急劇增加。
- 一個系統有兩個或多個變化維度且都需要擴展。
優缺點
優點
- 將抽象和具體實現分離開來。
- 提高了系統的可擴展性,改變或增加其中一個變化維度,不需要對另一個變化維度進行修改。
- 對客戶隱藏實現細節。
缺點
- 會增加理解難度。(這算缺點嗎?)
代碼
話不多說,直接上代碼(假設已#include
相應頭文件並using namespace std;
):
Graphics
類:
class Graphics
{
protected:
Color &color;
public:
Graphics(Color &color) : color(color) { }
virtual void draw() = 0;
}
Rectangle
類:
class Rectangle : public Graphics
{
public:
Rectangle(Color &color) : Graphics(color) { }
void draw() override
{
color.paint("矩形");
}
}
Circle
類:
class Circle : public Graphics
{
public:
Circle(Color &color) : Graphics(color) { }
void draw() override
{
color.paint("圓形");
}
}
Color
類:
class Color
{
public:
virtual void paint(string shape) = 0;
}
Red
類:
class Red : public Color
{
public:
void paint(string shape) override
{
cout << "繪製紅色的" << shape << endl;
}
}
Green
類:
class Green : public Color
{
public:
void paint(string shape) override
{
cout << "繪製綠色的" << shape << endl;
}
}
main
函數:
int main(int argc, char *argv[])
{
Red red();
Rectangle rectangle(red);
rectangle.draw();
return 0;
)