1. 程式人生 > >學習設計模式——橋接模式

學習設計模式——橋接模式

1. 認識橋接模式

    1. 定義:將抽象與實現分離,使它們可以獨立變化。用組合關係代替繼承關係來實現,從而降低了抽象和實現這兩個可變維度的耦合度。也就是說,通常我們會首先定義一個抽象化介面,然後再建立一個具體實現類繼承該介面,完成具體的功能實現。但是使用橋接後,我們會將這兩部分隔離,具體的功能實現類的一套介面以及實現類,以及定義所需功能的抽象類以及抽象實現類。抽象類定義所需功能,抽象實現類繼承抽象類,並且將功能實現類物件作為域物件,然後再抽象類定義的所需方法介面中呼叫功能實現類物件的方法。

    2. 模式的組成結構:

  • 抽象化(Abstraction)角色:定義抽象類,幷包含一個對具體實現物件的引用。
  • 擴充套件抽象化(Refined    Abstraction)角色:是抽象化角色的子類,實現父類中的業務方法,並通過組合關係調用具體實現角色中的業務方法。
  • 具體實現(Implementor)角色介面:定義具體實現角色的介面,介面中實現的功能是原本應該在擴充套件抽象化類中實現的,但獨立出來通過組合關係供擴充套件抽象化角色呼叫。
  • 具體實現(Concrete Implementor)角色:給出具體實現角色介面的具體實現。

    3. 參考程式碼實現:


public class BridgeTest
{
    public static void main(String[] args)
    {
        Implementor imple=new ConcreteImplementorA();
        Abstraction abs=new RefinedAbstraction(imple);
        abs.Operation();
    }
}
//實現化角色
interface Implementor
{
    public void OperationImpl();
}
//具體實現化角色
class ConcreteImplementorA implements Implementor
{
    public void OperationImpl()
    {
        System.out.println("具體實現化(Concrete Implementor)角色被訪問" );
    }
}
//抽象化角色
abstract class Abstraction
{
   protected Implementor imple;
   protected Abstraction(Implementor imple)
   {
       this.imple=imple;
   }
   public abstract void Operation();   
}
//擴充套件抽象化角色
class RefinedAbstraction extends Abstraction
{
   protected RefinedAbstraction(Implementor imple)
   {
       super(imple);
   }
   public void Operation()
   {
       System.out.println("擴充套件抽象化(Refined Abstraction)角色被訪問" );
       imple.OperationImpl();
   }
}

2. 理解橋接模式

    1. 應用場景:

  • 當一個類存在兩個獨立變化的維度,且這兩個維度都需要進行擴充套件時。比如桌上型電腦電腦的組裝,其中的主要部件幾乎都是可以互換的,主機板、顯示卡、cpu都是可以更換的。
  • 當一個系統不希望使用繼承或因為多層次繼承導致系統類的個數急劇增加時。
  • 當一個系統需要在構件的抽象化角色和具體化角色之間增加更多的靈活性時。

    2. 舉例:對於一個桌上型電腦的組裝來說,其主要元件包括處理器晶片、硬碟以及顯示器等,晶片提供資料計算功能、硬碟提供資料儲存功能、顯示器提供資料顯示功能,而桌上型電腦則會將這些元件組合起來,實現一個完整的計算機。

    但注意晶片、硬碟、顯示器都是可以隨意更換的,如果每一個計算機類中的晶片計算方法、資料顯示方法、資料儲存方法都是在電腦描述類中進行實現的話(繼承晶片介面、硬碟介面和顯示器介面),一旦想要更改某個部件的具體實現方法,就必須要修改計算機類或者重新建立一個計算機類,不符合開閉原則,。

    所以應該通過橋接模式,以組合的方式實現。橋接模式中的抽象化角色就相當於主機板的作用,主機板規定了所需要的功能介面以及元件,功能介面的具體實現由元件提供,同樣的,主機板也是可以更換的,所以說橋接模式是將抽象與實現分離的一種模式。

    3. 橋接模式與介面卡模式區別:兩者確實很相似,如果橋接模式中的變化維度(抽象化角色中包含的具體實現角色數量)只有一個的話,那實際上就是介面卡模式,但是橋接模式是應用於多個變化維度的。比如說一個電腦類(抽象化角色),其中包括顯示卡、主機板和CPU等(具體實現角色),每一個部件都有多種類可以更換,電腦類也需要這些元件所提供的功能,但不可能繼承這些介面去實現,因為一旦需要更換某個元件就需要更改電腦類,不符合開閉原則,而且代價過高,不利於複用。

    也就是說,介面卡模式指適用於只有一個變化維度的情況,如果有多個變化維度,就是橋接模式。

合成複用原則(Composite Reuse Principle,CRP)又叫組合/聚合複用原則(Composition/Aggregate Reuse Principle,CARP)。它要求在軟體複用時,要儘量先使用組合或者聚合等關聯關係來實現,其次才考慮使用繼承關係來實現。組合關係帶來的耦合性是低於繼承關係的。

通常類的複用分為繼承複用和合成複用兩種,繼承複用雖然有簡單和易實現的優點,但它也存在以下缺點,所以幾乎不使用。

  1. 繼承複用破壞了類的封裝性。因為繼承會將父類的實現細節暴露給子類,父類對子類是透明的,所以這種複用又稱為“白箱”複用。
  2. 子類與父類的耦合度高。父類的實現的任何改變都會導致子類的實現發生變化,這不利於類的擴充套件與維護。
  3. 它限制了複用的靈活性。從父類繼承而來的實現是靜態的,在編譯時已經定義,所以在執行時不可能發生變化。

採用組合或聚合複用時,可以將已有物件納入新物件中,使之成為新物件的一部分,新物件可以呼叫已有物件的功能,通常都使用該方式,它有以下優點。
  1. 它維持了類的封裝性。因為成分物件的內部細節是新物件看不見的,所以這種複用又稱為“黑箱”複用。
  2. 新舊類之間的耦合度低。這種複用所需的依賴較少,新物件存取成分物件的唯一方法是通過成分物件的介面。
  3. 複用的靈活性高。這種複用可以在執行時動態進行,新物件可以動態地引用與成分物件型別相同的物件。