首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

設計模式精講:橋接模式—— 讓抽象與實現獨立演化

     編輯:Java 綜合教學

場景引入:遙控器與電視的「組合爆炸」

假設市面有 多品牌電視(RCA、Sony、TCL...)與 多廠商遙控器(基本款、語音款、觸控款...)。傳統聚合方案:每種遙控器內部聚合一種電視接口,需為每種組合寫一個具體類(RCA基本遙控器、Sony語音遙控器...),類數量 = 遙控器種類 × 電視品牌,新增任意一方都引發類爆炸,維護成本極高。

橋接模式核心定義

將抽象部分與實現部分分離,使它們可以獨立地變化。 —— GoF
  • 抽象部分:遙控器(定義高層操作:開關、換台、音量)
  • 實現部分:電視機(定義底層實現:開機、關機、調頻)
  • 橋接關鍵:抽象類持有實現接口引用,而非繼承具體實現。雙方通過組合關聯,各自維度獨立擴展。

類圖結構

傳統聚合方案類爆炸
傳統方案:具體遙控器 × 具體電視 = 類爆炸
橋接模式類圖
橋接模式:抽象遙控器聚合 TV 接口,雙方獨立擴展

關鍵設計決策:為什麼 TV 接口聚合在 抽象類 RemoteControl 中,而非具體子類?
因為只有放在抽象層,所有遙控器子類自動獲得對所有電視品牌的支持,新增電視品牌零修改遙控器代碼;若放在子類,遙控器維度擴展時仍需重複聚合邏輯,違背橋接初衷。

代碼實戰

// 實現層接口:電視機
public interface TV {
    void on();
    void off();
    void tuneChannel(int channel);
}

// 具體實現:RCA 電視
public class RCA implements TV {
    @Override public void on() { System.out.println("RCA 開機"); }
    @Override public void off() { System.out.println("RCA 關機"); }
    @Override public void tuneChannel(int ch) { System.out.println("RCA 切換到 " + ch + " 台"); }
}

// 具體實現:Sony 電視
public class Sony implements TV { ... }

// 抽象層:遙控器(持有 TV 引用)
public abstract class RemoteControl {
    protected TV tv;
    public RemoteControl(TV tv) { this.tv = tv; }
    public abstract void on();
    public abstract void off();
    public void setChannel(int ch) { if (tv != null) tv.tuneChannel(ch); }
}

// 擴展抽象:具體遙控器(增加換台邏輯)
public class ConcreteRemote extends RemoteControl {
    private int current = 0;
    private static final int MAX = 25;
    public ConcreteRemote(TV tv) { super(tv); }
    @Override public void on() { tv.on(); }
    @Override public void off() { tv.off(); }
    @Override public void setChannel(int ch) { current = ch; super.setChannel(current); }
    public void nextChannel() { current = (MAX + current + 1) % MAX; super.setChannel(current); }
    public void prevChannel() { current = (MAX + current - 1) % MAX; super.setChannel(current); }
}

// 客戶端:任意組合
public class Client {
    public static void main(String[] args) {
        TV rca = new RCA();
        TV sony = new Sony();
        RemoteControl rc1 = new ConcreteRemote(rca);
        RemoteControl rc2 = new ConcreteRemote(sony);
        rc1.on(); rc1.setChannel(5); rc1.nextChannel();
        rc2.on(); rc2.setChannel(8); rc2.prevChannel();
    }
}

模式評價與適用場景

優點缺點
抽象與實現解耦,雙方獨立擴展,符合開閉原則增加系統理解難度,需識別兩個獨立變化維度
避免繼承導致的類爆炸,組合優於繼承雙層間接調用,極微量性能開銷(可忽略)
對客戶端屏蔽實現細節,提高靈活性不適用於單一固定實現的簡單場景

經典應用場景

  1. JDBC 驅動:Driver(抽象)+ 各廠商 Connection/Statement(實現),應用無感切換數據庫。
  2. 集合框架:List(抽象)+ ArrayList/LinkedList(實現),算法針對接口編程。
  3. 跨平台 GUI:Window(抽象)+ WindowsImpl/MacImpl(實現),Java AWT/SWT 採用此思想。
  4. 消息推送:Notifier(抽象:郵件/短信/推送)+ Provider(實現:SMTP/Twilio/APNs)。

總結:識別「兩個維度」是關鍵

橋接模式適用於 「抽象有多種變化、實現也有多種變化、且兩者需任意組合」 的場景。設計時問自己:
1. 系統中是否存在兩個正交變化維度?
2. 是否預期它們未來會獨立擴展?
3. 能否定義穩定的實現接口?
若答案全是 YES,果斷引入橋接,用組合替代繼承,賦予系統優雅的演化能力。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved