#橋接模式(Bridge Pattern)
##簡介
橋接模式把事物對象和其具體行為、具體特征分離開來,使它們可以各自獨立的變化。事物對象僅是一個抽象的概念。如“圓形”、“三角形”歸于抽象的“形狀”之下,而“畫圓”、“畫三角”歸于實現行為的“畫圖”類之下,然后由“形狀”調用“畫圖”。
如果有一個N品牌的手機,它有個小游戲,我要玩游戲,程序應該如何寫?
```
//N品牌的手機中的游戲
class HandSetNGame
{
public void Run()
{
Console.WriteLine("運行N品牌");
}
}
```
客戶端
```
HandSetNGame game = new HandSetGame();
game.run();
```
現在又有一個M品牌的手機,也是小游戲,客戶端也可以調用,如何做?
```
class HandSetGame
{
public virtual void Run()
{
}
}
```
M品牌手機游戲和N品牌手機游戲
```
class HandSetMGame : HandSetGanme
{
public override void Run()
{
Console.WriteLine("運行M品牌手機游戲");
}
}
class HandSetNGame : HandSetGanme
{
public override void Run()
{
Console.WriteLine("運行N品牌手機游戲");
}
}
```
然后,由于手機都需要通訊錄功能,于是N品牌和M品牌都增加了通訊錄的增刪該查功能,如何處理?
```
//手機品牌
class HandSetBrand
{
public virtual void run()
{
}
}
```
```
//手機品牌M
class HandSetBrandM:HandsetBrand
{
}
//手機品牌N
class HandSetBrandM:HandsetBrand
{
}
```
下屬的各自通訊錄類和游戲類
```
//手機品牌M的游戲
class HandSetBrandMGame:HandSetBrandM
{
public override void Run()
{
Console.WriteLine("運行M品牌手機游戲");
}
}
//手機品牌N的游戲
class HandSetBrandMGame:HandSetBrandM
{
public override void Run()
{
Console.WriteLine("運行N品牌手機游戲");
}
}
//手機品牌M的通訊錄
class HandSetBrandMAddressList:HandSetBrandM
{
public override void Run()
{
Console.WriteLine("運行M品牌手機通訊錄");
}
}
//手機品牌N的
class HandSetBrandMAddressList:HandSetBrandM
{
public override void Run()
{
Console.WriteLine("運行N品牌手機通訊錄");
}
}
```
客戶端調用代碼
```
static void Main(strring[] args)
{
HandSetBrand ab;
ab = new HandSetBrandMAddressList();
ab.Run();
ab = new HandSetBrandNAddressList();
ab.Run();
ab = new HandSetBrandMGame();
ab.Run();
ab = new HandSetBrandNGame();
ab.Run();
Console.Read();
}
```
如果我現在需要每個品牌都增加一個MP3音樂功能,如何做?還增加子類?
***對象的繼承關系是在編譯時就定義好的,所以無法在運行時改變從父類繼承的實現,子類的實現與它的父類有非常緊密的依賴關系,以至于父類實現中的任何變化必然會導致子類發生變化。當你需要復用子類時,如果繼承下來的實現不適合解決新的問題,則父類必須重寫或被其它更適合的類替換。這種依賴關系限制了靈活性并最終限制了復用性。***
***
***合成(Composition)/聚合(Aggregation)復用原則,盡量使用合成/聚合,盡量不要使用類繼承。***
***
聚合表示一種弱的'擁有'關系,體現的是A對象可以包含B對象,但是B對象不是A對象的一部分。合成則是一種強的'擁有'關系,體現了嚴格的部分和整體的關系,部分和整體的生命周期一樣。
比如說 大雁有翅膀,大雁和翅膀是部分和整體的關系,并且它們生命周期是一樣的,于是它們就是合成關系。而大雁是群居動物,所以每只大雁都屬于一個雁群,一個雁群可以有很多大雁,所以大雁和雁群是聚合關系。
***優先使用對象的合成/聚合將有助于你保持每個類被封裝,并被集中在單個任務上。這樣類和類繼承層次會保持較小規模,并且不太可能增長為不可控制的龐然大物。***
像'游戲','通訊錄','MP3音樂',如果我們可以讓其分離與手機的耦合,那么可以大大減少面對新需求改動過大的不合理情況。
松耦合的程序
```
//手機軟件
abstract class HandsetSoft
{
public abstract void Run();
}
```
游戲,通訊錄等具體類
```
//手機游戲
class HandsetGame : HandSetSoft
{
public override void Run()
{
Console.WriteLine("運行手機游戲");
}
}
//手機通訊錄
class HandsetAddressList : HandSetSoft
{
public override void Run()
{
Console.WriteLine("運行手機通訊錄");
}
}
```
```
//手機品牌
abstract class HandsetBrand
{
protected HandsetSoft soft;
//設置手機軟件
public void SetHandSetSoft(HandSetSoft soft)
{
this.soft = soft;
}
//運行
public abtract void run();
}
```
品牌N品牌M具體類
```
//手機品牌N
class HandSetBrandN: HandBrand
{
public override void Run()
{
soft.Run();
}
}
//手機品牌M
class HandSetBrandM: HandBrand
{
public override void Run()
{
soft.Run();
}
}
```
客戶端代碼
```
static void Mian(string[] args)
{
HandSetBrand ab;
ab = new HandSetBrandN();
ab.setHandSetSoft(new HandSetGame());
ab.run();
ab.setHandSetSoft(new HandSetAddressList());
ab.run();
ab = new HandSetBrandM();
ab.setHandSetSoft(new HandSetGame());
ab.run();
ab.setHandSetSoft(new HandSetAddressList());
ab.run();
Console.Read();
}
```
現在我們要再加個功能 比如說MP3功能,只要增加這個類就好了,不會影響其它任何類。
```
//手機MP3播放
class HandsetMP3 : HandSetSoft
{
public override void Run()
{
Console.WriteLine("運行手機MP3");
}
}
```
如果要增加S品牌,只需要增加一個品牌子類就可以了。
```
//手機品牌S
class HandSetBrand: HandSetBrand
{
public override void Run()
{
soft.Run();
}
}
```
###橋接模式
橋接模式:將抽象部分與它的實現部分分離,使它們都可以獨立地變化。
什么叫抽象與它的實現分離,這并不是說,讓抽象與其派生類分離,因為這沒有任何意義。實現指的是抽象類和它的派生類用來實現自己的對象。

橋接模式基本代碼

橋接模式把兩個角色之間的繼承關系改為聚合關系,從而使二者可以各自獨立的變化。把原來在基類的實現化細節抽象出來,再構造到一個實現化的結構中,然后把原來的基類改造成一個抽象化的等級結構,這樣就實現了系統在多個維度上的獨立變化。