標籤:

結構型模式之橋接模式

結構型模式之橋接模式

  • 橋接模式是一種很實用的結構型設計模式,如果軟體系統中某個類存在兩個獨立變化的維度,通過該模式可以將這兩個維度分離出來,使兩者可以獨立擴展,讓系統更加符合「單一職責原則」。與多層繼承方案不同,它將兩個獨立變化的維度設計為兩個獨立的繼承等級結構,並且在抽象層建立一個抽象關聯,該關聯關係類似一條連接兩個獨立繼承結構的橋,故名橋接模式。
  • 橋接模式用一種巧妙的方式處理多層繼承存在的問題,用抽象關聯取代了傳統的多層繼承,將類之間的靜態繼承關係轉換為動態的對象組合關係,使得系統更加靈活,並易於擴展,同時有效控制了系統中類的個數。橋接定義如下:
  • 橋接模式(Bridge Pattern):將抽象部分與它的實現部分分離,使它們都可以獨立地變化。它是一種對象結構型模式,又稱為柄體(Handle and Body)模式或介面(Interface)模式。

  • 在橋接模式結構圖中包含如下幾個角色:
    • Abstraction(抽象類):用於定義抽象類的介面,它一般是抽象類而不是介面,其中定義了一個Implementor(實現類介面)類型的對象並可以維護該對象,它與Implementor之間具有關聯關係,它既可以包含抽象業務方法,也可以包含具體業務方法。
    • RefinedAbstraction(擴充抽象類):擴充由Abstraction定義的介面,通常情況下它不再是抽象類而是具體類,它實現了在Abstraction中聲明的抽象業務方法,在RefinedAbstraction中可以調用在Implementor中定義的業務方法。
    • Implementor(實現類介面):定義實現類的介面,這個介面不一定要與Abstraction的介面完全一致,事實上這兩個介面可以完全不同,一般而言,Implementor介面僅提供基本操作,而Abstraction定義的介面可能會做更多更複雜的操作。Implementor介面對這些基本操作進行了聲明,而具體實現交給其子類。通過關聯關係,在Abstraction中不僅擁有自己的方法,還可以調用到Implementor中定義的方法,使用關聯關係來替代繼承關係。
    • ConcreteImplementor(具體實現類):具體實現Implementor介面,在不同的ConcreteImplementor中提供基本操作的不同實現,在程序運行時,ConcreteImplementor對象將替換其父類對象,提供給抽象類具體的業務操作方法。

實例

  • 從上面的這個實例我們可以看出,如果使用多層繼承的話,那麼我們可以定義是三個抽象類(台式機,筆記本,平板電腦),在這個三個抽象類的下面每個都有三個不同品牌的具體實現類,那麼總共要有3x3=9個具體的實現類。不僅僅是類的數量多,在擴展性能上也是成倍的增加,如果想要添加一個品牌,那麼需要添加三個類,這個是極其浪費的。
  • 針對上面的缺點,我們可以使用橋接模式,將電腦分類,品牌分類分成兩個維度,如下圖:

  • 其中Computer是一個抽象類,不是介面,其中Brand(品牌)是其中的成員變數,我們就完成了一個電腦具有不同品牌,那麼如果我們想添加一個品牌,就只是添加一個具體的實現類即可,就不需要添加三個了。
  • Computer(電腦的抽象類,表示台式,筆記本,平板電腦)
    • 其中的成員變數是Brand,採用組合的方式,替代了多繼承

/* * 電腦的抽象類,其中包括台式電腦,筆記本電腦,平板電腦 */public abstract class Computer { protected Brand brand; // 品牌的類 ,意味著具有不同的品牌,只需要初始化不同的具體類即可 /** * 構造方法 * @param brand Brand對象,可以表示不同的品牌類 */ public Computer(Brand brand) { this.brand = brand; } public void sale() { this.brand.sale(); //調用不同品牌的sale方法 }}

  • 台式機的實現類(繼承了Computer這個類)

/** * 台式機的類,繼承了Computer這個類 * @author Chenjiabing */public class Desktop extends Computer { /* * 構造方法 */ public Desktop(Brand brand) { super(brand); } @Override public void sale() { super.sale(); //調用父類的方法 System.out.println("銷售台式機......"); }}

  • 筆記本的實現類(繼承了Computer)

/** * 筆記本的類,繼承類Computer這個類 * @author Chenjiabing */public class LapTop extends Computer { /* * 構造方法 */ public LapTop(Brand brand) { super(brand); } @Override public void sale() { super.sale(); //調用了父類的sale方法 System.out.println("銷售筆記本電腦......"); }}

  • Brand介面(品牌的介面)

/* * 品牌的介面,有聯想,神州,華碩 */public interface Brand { void sale(); //sale方法}

  • 聯想的品牌(實現了Brand介面)

/** * 聯想品牌,實現了Brand介面 * @author Chenjiabing */public class Lenovo implements Brand { @Override public void sale() { System.out.println("銷售聯想品牌的電腦......"); }}

  • 華碩品牌(實現了Brand介面)

/** * 聯想品牌,實現了Brand介面 * @author Chenjiabing */public class Asus implements Brand { @Override public void sale() { System.out.println("銷售華碩品牌的電腦......"); }}

  • 測試類

public class Client { public static void main(String[] args) { Brand brand=new Lenovo(); //聯想品牌 Computer computer=new Desktop(brand); //創建電腦對象,其中的構造參數是聯想品牌的 computer.sale(); //調用sale方法 }}

使用場景

  1. 如果一個系統需要在構件的抽象化角色和具體化角色之間增加更多的靈活性,避免在兩個層次之間建立靜態的繼承聯繫,通過橋接模式可以使它們在抽象層建立一個關聯關係。
  2. 對於那些不希望使用繼承或因為多層次繼承導致系統類的個數急劇增加的系統,橋接模式尤為適用。
  3. 一個類存在兩個獨立變化的維度,且這兩個維度都需要進行擴展。

總結

  • 擴展性很強,如果想要添加一個電腦的種類或者添加一個品牌,只需要添加一個具體的實現類即可。並不需要成倍的添加。
  • 將多層繼承用了組合的方式實現了,即是品牌類作為電腦的一個成員變數,那麼就可以實現電腦擁有多種品牌。

推薦閱讀:

單例模式小結
遊戲開發與程序設計知識總結01——設計模式
可擴展性系統設計的思考
深入理解MVC
創建型模式之建造者模式

TAG:設計模式 |