Java 設計模式(七):橋接模式

橋接模式

橋接模式(Bridge),將抽象部分和它的實現部分分離,使它們都可以獨立地變化。

橋接模式基於類的最小設計原則,通過使用封裝、聚合及繼承等行爲讓不同的類承擔不同的職責。它的主要特點是把抽象與行爲實現分離開來,從而可以保持各部分的獨立性以及應對它們的功能擴展。

也就是說,實現系統可能有多種方式分類,每一種分類都有可能變化。橋接模式的核心意圖就是把這些分類獨立出來,讓它們各自獨立變化,減少它們之間的耦合。

橋接模式解析

橋接模式結構圖

角色介紹

  • Abstraction:維護了 Implementor 類,兩者是聚合關係,Abstraction 充當橋接類。
  • RefinedAbstraction:是 Abstraction 抽象類的子類。
  • Implementor:行爲實現類的接口。
  • ConcreteImplementorA/ConcreteImplementorA:行爲的具體實現類。

橋接模式基本代碼

  • Abstraction 類
public abstract class Abstraction {

    private Implementor implementor;

    public Abstraction(Implementor implementor) {
        this.implementor = implementor;
    }

    protected void operation() {
        implementor.operation();
    }
}
  • RefinedAbstraction 類
public class RefinedAbstraction extends Abstraction {

    public RefinedAbstraction(Implementor implementor) {
        super(implementor);
    }

    @Override
    protected void operation() {
        super.operation();
    }
}
  • Implementor 類
public interface Implementor {

    void operation();
}
  • ConcreteImplementorA 類
public class ConcreteImplementorA implements Implementor {

    @Override
    public void operation() {
        System.out.println("具體實現 A 的方法執行");
    }
}
  • ConcreteImplementorB 類
public class ConcreteImplementorB implements Implementor {

    @Override
    public void operation() {
        System.out.println("具體實現 B 的方法執行");
    }
}
  • Main 類
public class Main {

    public static void main(String[] args) {
        Implementor implementorA = new ConcreteImplementorA();
        Abstraction refinedAbstractionA = new RefinedAbstraction(implementorA);
        refinedAbstractionA.operation();

        Implementor implementorB = new ConcreteImplementorB();
        Abstraction refinedAbstractionB = new RefinedAbstraction(implementorB);
        refinedAbstractionB.operation();
    }
}

示例

手機操作問題,對不同品牌手機的不同軟件功能進行編程,如通訊錄、手機遊戲等。

傳統方法

  • 結構圖
    代碼結構圖

  • 手機類

/**
 * AbstractHandset
 */
public abstract class AbstractHandset {

    public abstract void run();
}
  • 手機品牌 M 和手機品牌 N 類
/**
 * HandsetM
 */
public abstract class HandsetM extends AbstractHandset {


}

/**
 * HandsetN
 */
public abstract class HandsetN extends AbstractHandset {
    
}
  • 手機遊戲類和手機 MP3 類
/**
 * HandsetMGame
 */
public class HandsetMGame extends HandsetM {

    @Override
    public void run() {
        System.out.println("運行 M 品牌手機的遊戲");
    }
}

/**
 * HandsetNGame
 */
public class HandsetNGame extends HandsetN {

    @Override
    public void run() {
        System.out.println("運行 N 品牌手機的遊戲");
    }
}

/**
 * HandsetMMP3
 */
public class HandsetMMP3 extends HandsetM {

    @Override
    public void run() {
        System.out.println("運行 M 品牌手機的 MP3");
    }
}

/**
 * HandsetNMP3
 */
public class HandsetNMP3 extends HandsetN {

    @Override
    public void run() {
        System.out.println("運行 N 品牌手機的 MP3");
    }
}
  • Main 類
/**
 * Main
 */
public class Main {

    public static void main(String[] args) {
        HandsetM handsetM = new HandsetMGame();
        handsetM.run();

        HandsetN handsetN = new HandsetNMP3();
        handsetN.run();
    }
}

傳統方法使用多層繼承的方案,在擴展上存在類爆炸的問題。當我們要給每個品牌的手機增加一個新功能時,就要在每個品牌的手機下面增加一個子類,這樣增加了代碼維護的成本。

事實上,很多情況下使用繼承會帶來麻煩。對象的繼承關係是在編譯時就定義好了的,所以無法在運行時改變從父類繼承的實現。子類的實現與它的父類有非常緊密的依賴關係,以至於父類實現中的任何變化必然導致其子類發生變化。當需要複用子類時,如果繼承下來的實現不適合解決新的問題,則父類必須重寫或被其他更適合的類替換。這種依賴關係限制了靈活性並最終限制複用。

使用橋接模式改進

  • 結構圖
    橋接模式
  • 手機軟件類
/**
 * HandsetSoft
 */
public interface HandsetSoft {

    void run();
}
  • 手機功能等具體類
/**
 * HandsetGame
 */
public class HandsetGame implements HandsetSoft {

    @Override
    public void run() {
        System.out.println("運行手機遊戲");
    }
}

/**
 * HandsetMP3
 */
public class HandsetMP3 implements HandsetSoft {

    @Override
    public void run() {
        System.out.println("運行手機 MP3");
    }
}
  • 手機類
/**
 * AbstractHandset
 */
public abstract class AbstractHandset {

    protected HandsetSoft handsetSoft;

    public AbstractHandset(HandsetSoft handsetSoft) {
        this.handsetSoft = handsetSoft;
    }

    public abstract void run();
}
  • 手機具體品牌類
/**
 * HandsetM
 */
public class HandsetM extends AbstractHandset {

    public HandsetM(HandsetSoft handsetSoft) {
        super(handsetSoft);
    }

    @Override
    public void run() {
        this.handsetSoft.run();
    }
}

/**
 * HandsetN
 */
public class HandsetN extends AbstractHandset {

    public HandsetN(HandsetSoft handsetSoft) {
        super(handsetSoft);
    }

    @Override
    public void run() {
        this.handsetSoft.run();
    }
}
  • Main 類
/**
 * Main
 */
public class Main {

    public static void main(String[] args) {
        HandsetM handsetM = new HandsetM(new HandsetGame());
        handsetM.run();

        HandsetN handsetN = new HandsetN(new HandsetMP3());
        handsetN.run();
    }
}

小結

橋接模式,實現了抽象和實現部分的分離,從而極大的提供了系統的靈活性,讓抽象部分和實現部分獨立開來,這有助於系統進行分層設計,從而產生更好的結構化系統。對於系統的高層部分,只需要知道抽象部分和實現部分的接口就可以了,其它的部分由具體業務來完成。橋接模式替代多層繼承方案,可以減少子類的個數,降低系統的管理和維護成本

橋接模式要求正確識別出系統中兩個獨立變化的維度(抽象和實現),因此其使用範圍有一定的侷限性,即需要有這樣的應用場景。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章