???? 橋接模式(GOF):指將抽象部分和實(shí)現(xiàn)部分分開(kāi),讓它們各自隨意增加減少。而不受其它約束。

?????適用環(huán)境:

u?????? 你不希望在抽象和它的實(shí)現(xiàn)部分之間有一個(gè)固定的綁定關(guān)系。例如這種情況可能是因?yàn)椋诔绦蜻\(yùn)行時(shí)刻實(shí)現(xiàn)部分應(yīng)可以被選擇或者切換。

u?????? 類(lèi)的抽象以及它的實(shí)現(xiàn)都應(yīng)該可以通過(guò)生成子類(lèi)的方法加以擴(kuò)充。這時(shí)Bridge模式使你可以對(duì)不同的抽象接口和實(shí)現(xiàn)部分進(jìn)行組合,并分別對(duì)它們進(jìn)行擴(kuò)充。

u?????? 對(duì)一個(gè)抽象的實(shí)現(xiàn)部分的修改應(yīng)對(duì)客戶(hù)不產(chǎn)生影響,即客戶(hù)的代碼不必重新編譯。

u?????? C++)你想對(duì)客戶(hù)完全隱藏抽象的實(shí)現(xiàn)部分。在C++中,類(lèi)的表示在類(lèi)接口中是可見(jiàn)的。

u?????? 有許多類(lèi)要生成。這樣一種類(lèi)層次結(jié)構(gòu)說(shuō)明你必須將一個(gè)對(duì)象分解成兩個(gè)部分。Rumbaugh 稱(chēng)這種類(lèi)層次結(jié)構(gòu)為“嵌套的普化”(nested generalizations )。

u?????? 你想在多個(gè)對(duì)象間共享實(shí)現(xiàn)(可能使用引用計(jì)數(shù)),但同時(shí)要求客戶(hù)并不知道這一點(diǎn)。

為什么使用?
?????? 不希望抽象部分和行為有一種固定的綁定關(guān)系,而是應(yīng)該可以動(dòng)態(tài)聯(lián)系的。

如果一個(gè)抽象類(lèi)或接口有多個(gè)具體實(shí)現(xiàn)(子類(lèi)、concrete subclass),這些子類(lèi)之間關(guān)系可能有以下兩種情況:
1. 這多個(gè)子類(lèi)之間概念是并列的,如前面舉例,打樁,有兩個(gè)concrete class:方形樁和圓形樁;這兩個(gè)形狀上的樁是并列的,沒(méi)有概念上的重復(fù)。

2.這多個(gè)子類(lèi)之中有內(nèi)容概念上重疊.那么需要我們把抽象共同部分和行為共同部分各自獨(dú)立開(kāi)來(lái),原來(lái)是準(zhǔn)備放在一個(gè)接口里,現(xiàn)在需要設(shè)計(jì)兩個(gè)接口:抽象接口和行為接口,分別放置抽象和行為.

例如,一杯咖啡為例,子類(lèi)實(shí)現(xiàn)類(lèi)為四個(gè):中杯加奶、大杯加奶、 中杯不加奶、大杯不加奶。

但是,我們注意到:上面四個(gè)子類(lèi)中有概念重疊,可從另外一個(gè)角度進(jìn)行考慮,這四個(gè)類(lèi)實(shí)際是兩個(gè)角色的組合:抽象 和行為,其中抽象為:中杯和大杯;行為為:加奶 不加奶(如加橙汁 加蘋(píng)果汁).

實(shí)現(xiàn)四個(gè)子類(lèi)在抽象和行為之間發(fā)生了固定的綁定關(guān)系,如果以后動(dòng)態(tài)增加加葡萄汁的行為,就必須再增加兩個(gè)類(lèi):中杯加葡萄汁和大杯加葡萄汁。顯然混亂,擴(kuò)展性極差。

那我們從分離抽象和行為的角度,使用Bridge模式來(lái)實(shí)現(xiàn)。

如何實(shí)現(xiàn)?
以上面提到的咖啡 為例. 我們?cè)瓉?lái)打算只設(shè)計(jì)一個(gè)接口(抽象類(lèi)),使用Bridge模式后,我們需要將抽象和行為分開(kāi),加奶和不加奶屬于行為,我們將它們抽象成一個(gè)專(zhuān)門(mén)的行為接口.
??? 先看看抽象部分的接口代碼:

package?bridge;
public?abstract?class?Coffee{
????CoffeeImpl?coffeeImpl
=null;
????
????
public?void?setCoffeeImpl(){
????????
this.coffeeImpl=CoffeeImplSingleton.getCoffeeImpl();
????}

????
????
public?CoffeeImpl?getCoffeeImpl(){
????????
return?this.coffeeImpl;
????}

????
????
public?abstract?void??pourCoffee();
}

其中CoffeeImp 是加不加奶的行為接口,看其代碼如下
package?bridge;
public?abstract?class?CoffeeImpl{
????
public?abstract?void?pourCoffeeImpl();
}
現(xiàn)在我們有了兩個(gè)抽象類(lèi),下面我們分別對(duì)其進(jìn)行繼承,實(shí)現(xiàn)concrete class
package?bridge;
//中杯Coffee
public?class?MediumCoffee??extends?Coffee{
????
????
public?MediumCoffee?(){
????????setCoffeeImpl();
????}

????
????
public?void?pourCoffee(){
????????CoffeeImpl?coffeeImp
=this.getCoffeeImpl();?
????????coffeeImpl.pourCoffeeImpl();
????}

}
package?bridge;
//大杯Coffee
public?class?SuperSizeCoffee?extends?Coffee{
????
public?SuperSizeCoffee?(){
????????setCoffeeImpl();
????}

????
????
public?void?pourCoffee(){
????????CoffeeImpl?coffeeImp
=this.getCoffeeImpl();?
????????coffeeImpl.pourCoffeeImpl();
????}

}

下面對(duì)行為CoffeeImp進(jìn)行繼承:
package?bridge;
//不加牛奶
public?class?FragrantCoffeeImpl?extends?CoffeeImpl{
????
public?void?pourCoffeeImpl(){
????????System.out.println(
"沒(méi)有加牛奶的Coffee");
????}

}
package?bridge;
//加牛奶
public?class?CoffeeImplSingleton{
????
private?static?CoffeeImpl?coffeeImpl;
????
public?CoffeeImplSingleton(CoffeeImpl?coffeeImpl){
????????
this.coffeeImpl=coffeeImpl;
????}
?
????
public?static?CoffeeImpl?getCoffeeImpl(){
????????
return?coffeeImpl;
????}

}

最后實(shí)現(xiàn):
package?bridge;
public?class?Bridge{
????
public?static?void?main(String[]?args){
???????
???????
//中杯加奶
???????CoffeeImplSingleton?coffeeImpl=new?CoffeeImplSingleton(new?MilkCoffeeImpl());
???????MediumCoffee?mediumCoffee?
=?new?MediumCoffee();
???????mediumCoffee.pourCoffee();
???????
???????
//大杯不加奶
???????CoffeeImplSingleton?coffeeImpl2=new?CoffeeImplSingleton(new?FragrantCoffeeImpl());
???????SuperSizeCoffee?superSizeCoffee?
=?new?SuperSizeCoffee();
???????superSizeCoffee.pourCoffee();

????}

}
運(yùn)行結(jié)果:
加了牛奶的Coffee
沒(méi)有加牛奶的Coffee
Press any key to continue...

與適配器模式的區(qū)別:橋接模式與對(duì)象形式的適配器模式很相似,然而適配器的目的是要改變已有的接口,讓它們可以相容,以使沒(méi)有關(guān)系的兩個(gè)類(lèi)能一起工作,而橋接模式是分離抽象化與實(shí)現(xiàn)化,以使兩者的接口可以不同。因此,兩模式是往兩個(gè)相反方面努力的。

參考資料:
http://www.jdon.com/designpatterns/bridge.htm(本篇的主要來(lái)源)
????????????????????
http://www.lvjiyong.com/books/DesignPatterns/20.html
???????????????????? 《Java與模式》