### 一、寫在前面
之前有讀者評論說,前邊的文章開頭理論性太強了,顯得晦澀難懂,會把讀者搞暈,謝謝這位讀者,同時也希望其他的讀者多提意見,幫助我改正提高博客,為了改進之前的問題,今天我們先用例子引入,然后再給出橋梁模式的相關概念。
### 二、問題引入
例子1:
現需要提供大中小3種型號的畫筆,能夠繪制5種不同顏色,如果使用蠟筆,我們需要準備3*5=15支蠟筆,也就是說必須準備15個具體的蠟筆類。而如果使用毛筆的話,只需要3種型號的毛筆,外加5個顏料盒,用3+5=8個類就可以實現15支蠟筆的功能。實際上,**蠟筆和毛筆的關鍵一個區別就在于筆和顏色是否能夠分離。**
例子2:
設想如果要繪制矩形、圓形、橢圓、正方形,我們至少需要4個形狀類,但是如果繪制的圖形需要具有不同的顏色,如紅色、綠色、藍色等,此時至少有如下兩種設計方案:
第一種設計方案是為每一種形狀都提供一套各種顏色的版本。

這種設計方案就是類似于實例一中的蠟筆,顏色和形狀緊密結合起來,必須為每一種形狀準備各種顏色的版本,加入我們現在要求加入一種顏色藍色,那么每一種形狀都需要修改,所以這種設計方案的缺點是顯而易見的,一是不符合“開-閉”原則,二是需要的類非常多,編碼重復性較高。
第二種設計方案是根據實際需要對形狀和顏色進行組合。

上下兩部分圖是分別從不同的角度描述這種方案,上邊的圖說的是如何利用形狀和顏色進行組合,下邊的圖說的是各個類的繼承和組合關系。第二種方案需要為所有的圖形聲明一個共同的父類,為所有的顏色聲明一個父類,兩個父類各有自己的具體實現,我們需要的產品就是有兩種具體的產品進行組合得到的。這樣在加入新的顏色或者形狀的時候不用修改其他的類,而且大大的減少了代碼量。而這第二種方案就是我們今天要討論的橋梁模式。
### 三、什么是橋梁模式
上邊的蠟筆和圖形的例子他們都有一個共同的特點就是他們都有兩個變化因素,蠟筆是粗細和形狀,圖形是形狀和顏色,不管是毛筆還是圖形的第二種解決方案他們比較好的原因都是將這兩種變化因素分開了,使得兩種因素可以獨立的變化。蠟筆的顏色和蠟筆本身是分不開的,所以就造成必須使用15支色彩、大小各異的蠟筆來繪制圖畫。而毛筆與顏料能夠很好的分開,各自獨立變化,便簡化了操作。
**所以橋梁模式的用意是“將抽象化與實現化脫耦,使得二者可以獨立地變化。”**
那么什么是脫耦呢?我們先來看一下什么是耦合。兩個類之間的關系分為兩種,一種是強關聯一種是弱關聯,強關聯是在編譯時期就已經確定的,無法在運行時期動態的改變的關聯;弱關聯是可以動態地確定并且可以在運行時期動態改變的關聯。顯然,Java中繼承是強關聯而聚合是弱關聯。耦合就是兩個實體的行為的某種強關聯,脫耦就是指將他們之間的強關聯解除,但是在橋梁模式中是指將它們之間的強關聯改換成弱關聯。所以橋梁模式的精髓就是盡量使用聚合/組合來實現弱關聯。
### 四、橋梁模式的結構

這是具有一般性的橋梁模式的類圖,我們可以看到橋梁模式一共有四部分組成:
- 抽象化角色:抽象化給出的定義,并保存一個對實現化對象的引用,就是圖像類中的形狀父類。
- 修正抽象化角色:擴展抽象化角色,改變和修正父類對抽象化的定義,比如形狀下有正方形,圓形等圖形。
- 實現化角色:這個角色給出具體角色的接口,但是不給出具體的實現,這個接口不一定和抽象化角色的接口定義相同,實際上兩者可以完全不一樣,好比形狀的顏色接口。
- 具體實現化角色:這個角色給出實現化角色接口的具體實現,好比各種具體的顏色。
如果將Abstraction和Implementor看成兩個岸邊的話,那么聚合關系就像橋一樣將他們連接起來,這就是這個模式為什么叫橋梁模式的原因。
### 五、橋梁模式的例子
我們來實現一下上邊的毛筆的例子,套用上邊的橋梁模式的類圖我們可以畫出毛筆的類圖。

~~~
package com.designpattern.bridge;
/**
* 這是抽象畫筆類
* @author 98583
*
*/
public abstract class BrushPenAbstraction {
/**
* 保留對顏色的引用
*/
protected ImplementorColor imp;
/**
* 每種筆都有自己的實現
*/
public abstract void operationDraw();
public void setImplementor(ImplementorColor imp) {
this.imp = imp;
}
}
~~~
~~~
package com.designpattern.bridge;
/**
* 粗毛筆的實現
* @author 98583
*
*/
public class BigBrushPenRefinedAbstraction extends BrushPenAbstraction{
public void operationDraw() {
System.out.println("Big and "+imp.bepaint()+" drawing!");
}
}
~~~
~~~
package com.designpattern.bridge;
/**
* 顏色的接口
* @author 98583
*
*/
public abstract class ImplementorColor {
public abstract String bepaint();
}
~~~
~~~
package com.designpattern.bridge;
/**
* 紅色的具體實現
* @author 98583
*
*/
public class OncreteImplementorRed extends ImplementorColor{
public String bepaint() {
return "red";
}
}
~~~
~~~
package com.designpattern.bridge;
/**
* 客戶端
* @author 98583
*
*/
public class Client {
public static void main(String[] args) {
BrushPenAbstraction brushPen = new BigBrushPenRefinedAbstraction();
ImplementorColor col = new OncreteImplementorRed();
/**
* 設置顏色
*/
brushPen.setImplementor(col);
/**
* 畫畫
*/
brushPen.operationDraw();
}
}
~~~
其他的類都是類似的,不再給出,最后會附上源碼。
### 五、橋梁模式的優缺點
橋接模式的優點:
1、分離抽象接口及其實現部分。
2、橋接模式提高了系統的可擴充性,在兩個變化維度中任意擴展一個維度,都不需要修改原有系統。
3、實現細節對客戶透明,可以對用戶隱藏實現細節。
橋接模式的缺點:
1、橋接模式的引入會增加系統的理解與設計難度,由于聚合關聯關系建立在抽象層,要求開發者針對抽象進
2、橋接模式要求正確識別出系統中兩個獨立變化的維度,因此其使用范圍具有一定的局限性。
源碼下載:[http://download.csdn.net/detail/xingjiarong/9316367](http://download.csdn.net/detail/xingjiarong/9316367)
- 前言
- 設計原則(一)"開-閉"原則(OCP)
- 設計原則(二)里氏替換原則(LSP)
- 設計原則(三)組合復用原則
- 設計原則(四)依賴倒置原則(DIP)
- 設計模式(一)簡單工廠模式
- 設計模式(二)工廠方法模式
- 設計模式(三)抽象工廠模式
- 設計模式(四)單例模式
- 設計模式(五)創建者模式(Builder)
- 設計模式(六)原型模式
- 設計模式(七)門面模式(Facade Pattern 外觀模式)
- 設計模式(八)橋梁模式(Bridge)
- 設計模式(九)裝飾模式(Decorator)
- 設計模式(十)適配器模式
- 設計模式(十一)策略模式
- 設計模式(十二)責任鏈模式
- 設計模式之UML(一)類圖以及類間關系(泛化 、實現、依賴、關聯、聚合、組合)
- 設計模式之橋梁模式和策略模式的區別