描述
定義
將抽象部分與它的實現部分分離,使它們都可以獨立地變化。橋接模式(Bridge Pattern)又稱爲柄體(Handle/Body)模式。
類型
對象結構型模式
UML類圖
時序圖
簡介
當一個抽象可能有多個實現時,通常用繼承來協調它們。抽象類定義對該抽象的接口,而具體的子類則用不同方式加以實現。但是此方法有時不夠靈活。繼承機制將抽象部分與它的實現部分固定在一起,使得難以對抽象部分和實現部分獨立地進行修改、擴充和重用。Bridge模式將抽象和它的實現部分分別放在獨立的類層次結構中,使它們可以獨立地變化。
實現
主要角色
- Abstraction:抽象類接口,維護一個Implementor類型對象的引用。
- RefinedAbstraction:擴充抽象類,擴充由Abstraction定義的接口。
- Implementor:實現類接口,該接口不一定要與Abstraction的接口完全一致;事實上這兩個接口可以完全不同。一般來講,Implementor接口僅提供基本操作,而Abstraction則定義了基於這些基本操作的較高層次的操作。
- ConcreteImplementor:具體實現類,實現Implementor接口並定義它的具體實現。
示例
以評價一個地方紅燒肉的口味爲例,這裏有兩個維度的變化:地域和餐館品牌。
-
Abstraction:城市抽象類,包含了一個Restaurant(Implementor)引用。
public abstract class AbstractCityArea { protected Restaurant restaurant; public AbstractCityArea(Restaurant restaurant) { this.restaurant = restaurant; } public abstract void commentTaste(); }
-
Implementor: 實現類接口,餐館的接口。
interface Restaurant { String taste(); }
-
ConcreteImplementor:具體實現類,具體的餐館:小南國和外婆家。
public class XiaoNanGuo implements Restaurant { @Override public String taste() { return "紅燒肉比較好吃"; } } public class WaiPojia implements Restaurant { @Override public String taste() { return "紅燒肉比較一般"; } }
-
RefinedAbstraction:擴充抽象類,具體的城市類。
public class NanjingRestaurant extends AbstractCityArea { public NanjingRestaurant(Restaurant restaurant) { super(restaurant); } @Override public void commentTaste() { System.out.println("南京的" + super.restaurant.taste()); } } public class ShanghaiRestaurant extends AbstractCityArea { public ShanghaiRestaurant(Restaurant restaurant) { super(restaurant); } @Override public void commentTaste() { System.out.println("上海的" + super.restaurant.taste()); } }
-
Client:客戶類
public class Client { public static void main(String[] args) { // 去了上海要吃紅燒肉,正好他去了小南國,這時候他要評價了 Restaurant rest1 = new XiaoNanGuo(); AbstractCityArea sr1 = new ShanghaiRestaurant(rest1); sr1.commentTaste(); // 又來到南京,去外婆家去吃紅燒肉,吃完又要評價了 Restaurant rest2 = new WaiPojia(); AbstractCityArea sr2 = new NanjingRestaurant(rest2); sr2.commentTaste(); } }
適用場景
- 如果一個系統需要在構件的抽象化角色和具體化角色之間增加更多的靈活性,避免在兩個層次之間建立靜態的繼承聯繫,通過橋接模式可以使它們在抽象層建立一個關聯關係。
- 抽象化角色和具體化角色可以以繼承的方式獨立擴展而互不影響,在程序運行時可以動態將一個抽象化子類的對象和一個具體化子類的對象進行組合,即系統需要對抽象化角色和具體化角色進行動態耦合。
- 一個類存在兩個獨立變化的維度,且這兩個維度都需要進行擴展。
- 對於那些不希望使用繼承或因爲多層次繼承導致系統類的個數急劇增加的系統,橋接模式尤爲適用。
優點
- 分離接口及其實現部分。一個實現未必不變地綁定在一個接口上。抽象類的實現可以在運行時刻進行配置,一個對象甚至可以在運行時刻改變它的實現。
- 橋接模式有時類似於多繼承方案,但是多繼承方案違背了類的單一職責原則(即一個類只有一個變化的原因),複用性比較差,而且多繼承結構中類的個數非常龐大,橋接模式是比多繼承方案更好的解決方法。
- 提高可擴充性,在兩個變化維度中任意擴展一個維度,都不需要修改原有系統。
- 實現細節對客戶透明。可以對客戶隱藏實現細節。
缺點
- 橋接模式的引入會增加系統的理解與設計難度,由於聚合關聯關係建立在抽象層,要求開發者針對抽象進行設計與編程。
- 橋接模式要求正確識別出系統中兩個獨立變化的維度,因此其使用範圍具有一定的侷限性。
相關模式
- Abstract Factory模式可以用來創建和配置一個特定的Bridge模式。通常用於Abstraction只能使用特定的Implementor的情況。在這種情況下, 可以用Abstract Factory封裝Client代碼中建立Abstraction和Implementor連接的部分。
- Adapter模式用來幫助無關的類協同工作,它通常在系統設計完成後纔會被使用。然而,Bridge模式則是在系統開始時就被使用,它使得抽象接口和實現部分可以獨立進行改變。
- Builder可以和Bridge一起使用,Director作爲Abstraction多個Builder作爲Implementor。