1. 程式人生 > 其它 >【設計模式從入門到精通】06-橋接模式

【設計模式從入門到精通】06-橋接模式

橋接模式

筆記來源:尚矽谷Java設計模式(圖解+框架原始碼剖析)

目錄

橋接模式

1、傳統方式解決手機操作問題

現在對不同手機型別的不同品牌實現操作程式設計(比如:開機、關機、上網,打電話等),如圖:

UML 類圖

問題分析

  1. 擴充套件性問題(類爆炸):如果我們再增加手機的樣式(旋轉式),就需要增加各個品牌手機的類;同樣如果我們增加一個手機品牌,也要在各個手機樣式類下增加
  2. 違反了單一職責原則:當我們增加手機樣式時,要同時增加所有品牌的手機,這樣增加了程式碼維護成本
  3. 解決方案——使用橋接模式

2、橋接模式基本介紹

  1. 橋接模式(Bridge模式):一種結構型設計模式:將實現與抽象放在兩個不同的類層次中,使兩個層次可以獨立改變
  2. Bridge模式基於類的最小設計原則,通過使用封裝、聚合及繼承等行為讓不同的類承擔不同的職責
  3. 它的主要特點是把抽象(Abstraction)與行為實現(Implementation)分離開來,從而可以保持各部分的獨立性以及應對他們的功能擴充套件

原理類圖

原理類圖說明

  • Client:橋接模式的呼叫者
  • Abstraction:Abstraction 充當橋接類,維護了 Implementor,即 ConcreteImplementorA / ConcreteImplementorB
  • RefinedAbstraction:Abstraction 抽象類的子類
  • Implementor:行為實現類的介面
  • ConcreteImplementorA / ConcreteImplementorB:行為的具體實現類
  • 這裡的抽象類和介面是聚合的關係,也是呼叫者和被呼叫者的關係

3、橋接模式解決手機操作問題

UML 類圖

核心程式碼

// 行為介面——品牌介面
public interface Branch {
    void open();

    void call();

    void close();
}
// 行為實現類——華為品牌
public class Huawei implements Branch {
    @Override
    public void open() {
        System.out.println("華為手機開機");
    }

    @Override
    public void call() {
        System.out.println("華為手機打電話");
    }

    @Override
    public void close() {
        System.out.println("華為手機關機");
    }
}
// 行為實現類——小米品牌
public class Xiaomi implements Branch {
    @Override
    public void open() {
        System.out.println("小米手機開機");
    }

    @Override
    public void call() {
        System.out.println("小米手機打電話");
    }

    @Override
    public void close() {
        System.out.println("小米手機關機");
    }
}
// 行為實現類——蘋果品牌
public class iPhone implements Branch {
    @Override
    public void open() {
        System.out.println("蘋果手機開機");
    }

    @Override
    public void call() {
        System.out.println("蘋果手機打電話");
    }

    @Override
    public void close() {
        System.out.println("蘋果手機關機");
    }
}

// 橋接類——手機抽象類
public abstract class Phone {
    private Branch branch;

    public Phone(Branch branch) {
        this.branch = branch;
    }

    public void open() {
        branch.open();
    }

    public void call() {
        branch.call();
    }

    public void close() {
        branch.close();
    }
}
// 橋接子類——翻蓋式手機
public class FlipPhone extends Phone {
    public FlipPhone(Branch branch) {
        super(branch);
        System.out.println("翻蓋式手機");
    }

    @Override
    public void open() {
        super.open();
    }

    @Override
    public void call() {
        super.call();
    }

    @Override
    public void close() {
        super.close();
    }
}
// 橋接子類——滑蓋式手機
public class SlidePhone extends Phone {
    public SlidePhone(Branch branch) {
        super(branch);
        System.out.println("滑蓋式手機");
    }

    @Override
    public void open() {
        super.open();
    }

    @Override
    public void call() {
        super.call();
    }

    @Override
    public void close() {
        super.close();
    }
}
// 橋接子類——直立式手機
public class UprightPhone extends Phone {
    public UprightPhone(Branch branch) {
        super(branch);
        System.out.println("直立式手機");
    }

    @Override
    public void open() {
        super.open();
    }

    @Override
    public void call() {
        super.call();
    }

    @Override
    public void close() {
        super.close();
    }
}

4、JDK 原始碼分析

JDBC 的 Driver 介面:如果從橋接模式來看,Driver 就是一個介面,下面可以有 MySQL 的 Driver、Oracle 的 Driver,這些就可以當做實現介面類

Connection 繼承體系

Driver原始碼

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    static {
        try {
            java.sql.DriverManager.registerDriver(new Driver());
        } catch (SQLException E) {
            throw new RuntimeException("Can't register driver!");
        }
    }
    public Driver() throws SQLException {
        // Required for Class.forName().newInstance()
    }
}

DriverManager 結構

說明

  • MySQL 有自己的 Connectionlmpl 類,同樣 Oracle 也有對應的實現類
  • Driver 和 Connection 之間是通過 DriverManager 類進行橋連線的

5、注意事項和細節

  1. 實現了抽象和實現部分的分離,從而極大的提供了系統的靈活性,讓抽象部分和實現部分獨立開來。這有助於系統進行分層設計,從而產生更好的結構化系統
  2. 對於系統的高層部分,只需要知道抽象部分和實現部分的介面就可以了,其它的部分由具體業務來完成
  3. 橋接模式替代多層繼承方案,可以減少子類的個數,降低系統的管理和維護成本
  4. 橋接模式的引入增加了系統的理解和設計難度,由於聚合關聯關係建立在抽象層,要求開發者針對抽象進行設計和程式設計
  5. 橋接模式要求正確識別出系統中兩個獨立變化的維度,因此其使用範圍有一定的後限性,即需要有這樣的應用場景

6、橋接模式其他應用場景

對於那些不希望使用繼承或因為多層次繼承導致系統類的個數急劇增加的系統,橋接模式尤為適用

常見的應用場景

  1. JDBC 驅動程式
  2. 銀行轉賬系統
    • 轉賬分類:網上轉賬、櫃檯轉賬、AMT 轉賬
    • 轉賬使用者型別:普通使用者、銀卡使用者、金卡使用者
  3. 訊息管理
    • 訊息型別:即時訊息、延時訊息
    • 訊息分類:手機簡訊、郵件訊息、QQ訊息…