設計模式 – 橋接模式詳解

  • 2020 年 3 月 30 日
  • 筆記

基本介紹

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

UML 類圖

橋接模式案例

我們以手機為例,手機有品牌(諾基亞、摩托羅拉)和樣式(摺疊式、直立式),我們需要生產不同的品牌和樣式,比如摺疊式諾基亞、直立式摩托羅拉… …

「抽象」 – 手機品牌,都有開機和關機的功能

public interface PhoneBrand {      void open();      void close();  }  

「具體」 – 手機品牌 Nokia 和 Moto

public class Nokia implements PhoneBrand {      @Override      public void open() {          System.out.println("諾基亞開機...");      }        @Override      public void close() {          System.out.println("諾基亞關機...");      }  }  
public class Moto implements PhoneBrand {      @Override      public void open() {          System.out.println("摩托羅拉開機...");      }        @Override      public void close() {          System.out.println("摩托羅拉關機...");      }  }  

「抽象」 – 手機類,以聚合的方式與品牌產生聯繫,充當著「橋」的角色

public abstract class AbsPhone{        private PhoneBrand brand;        public AbsPhone(PhoneBrand brand) {          this.brand = brand;      }        protected void open(){          brand.open();      }        protected void close(){          brand.close();      }  }  

「具體」 – 摺疊式手機 和 直立式手機

public class FoldingPhone extends AbsPhone{        public FoldingPhone(PhoneBrand brand) {          super(brand);      }        @Override      protected void open() {          System.out.print("摺疊式 - ");          super.open();      }        @Override      protected void close() {          System.out.print("摺疊式 - ");          super.close();      }  }  
public class UpRightPhone extends AbsPhone{        public UpRightPhone(PhoneBrand brand) {          super(brand);      }        @Override      protected void open() {          System.out.print("直立式 - ");          super.open();      }        @Override      protected void close() {          System.out.print("直立式 - ");          super.close();      }  }  

測試

@Test  public void test(){      AbsPhone p1 = new FoldingPhone(new Nokia());      p1.open();      p1.close();      System.out.println();      AbsPhone p2 = new UpRightPhone(new Moto());      p2.open();      p2.close();  }  

結果

摺疊式 - 諾基亞開機...  摺疊式 - 諾基亞關機...    直立式 - 摩托羅拉開機...  直立式 - 摩托羅拉關機...  

如果我們想創建其他類型的手機,只需要改變創建方式即可。

橋接模式分析

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

橋接模式在 JDBC 中的應用

在 Java 中我們通常使用 JDBC 連接數據庫,但是數據庫的種類有很多(MySQL、Oracle…),它們的連接方式、協議都不盡相同,很顯然不能為每種數據庫都寫一個接口,這樣就違背了精簡設計原則,於是Java設計師就提供一套接口給廠商們自己實現,一套接口給用戶調用。

我們在使用 JDBC 的時候需要寫這樣的代碼

Class.forName("數據庫驅動名");  Connection conn = DriverManager.getConnection("數據庫url", "用戶名", "密碼");  

其過程是這樣的:

  • Class.forName() 的時候,通過反射機制,將 .class 文件加載進Java虛擬機內存中,Driver 類初始化,執行以下代碼,向 DriverManager 中註冊一個驅動。DriverManager是個 Driver 容器,管理不同的 Driver

    static {      try {          DriverManager.registerDriver(new Driver());      } catch (SQLException var1) {          throw new RuntimeException("Can't register driver!");      }  }  
  • 我們獲取連接時,DriverManager 就會根據驅動返回一個相應的數據庫連接

    @CallerSensitive  public static Connection getConnection(String url,      java.util.Properties info) throws SQLException {      return (getConnection(url, info, Reflection.getCallerClass()));  }  

實際應用場景

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

  • 銀行轉賬系統
    • 轉賬分類:網上轉賬,櫃檯轉賬,AMT 轉賬
    • 轉賬用戶類型:普通用戶,銀卡用戶,金卡用戶…
  • 消息管理
    • 消息類型:即時消息,延時消息
    • 消息分類:手機短訊,郵件消息,QQ 消息…