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

Java 設計模式:適配器模式深度解析

     編輯:Java 程式設計入門

模式定義

適配器模式將一個類別的介面轉換成客戶端期望的另一個介面,使原本介面不兼容的類別能夠合作。別名:Wrapper(包裝器)。

兩種實作形式

1. 類別適配器

機制: 透過繼承源類別,實作目標介面。

結構:

Target (介面)
    ↑ 實作
Adapter → 繼承 → Adaptee (源類別)

2. 物件適配器

機制: 透過組合持有源物件參考,實作目標介面。

結構:

Target (介面)
    ↑ 實作
Adapter → 組合 → Adaptee (源類別)

完整程式碼範例

場景:坐騎系統演進

古代坐騎只能 run(),現代坐騎需同時支援 run() 與 fly()。

核心介面定義


// 目標介面:現代坐騎標準
public interface IModernMount {
    void run();
    void fly();
}

// 源類別:古代坐騎(只能跑)
public class AncientMount {
    public void run() {
        System.out.println("古代坐騎:在地上奔跑...");
    }
}

類別適配器實作


/**
 * 類別適配器:繼承 AncientMount,實作 IModernMount
 * 優點:可覆寫源類別方法;缺點:Java 單繼承限制,無法適配多個源類別
 */
public class ClassAdapter extends AncientMount implements IModernMount {
    
    @Override
    public void fly() {
        System.out.println("類別適配器:獲得飛行能力,騰空而起!");
    }
    
    // run() 直接繼承自 AncientMount,無需重寫
}

物件適配器實作


/**
 * 物件適配器:組合 AncientMount,實作 IModernMount
 * 優點:可適配多個源物件、無繼承限制、符合組合優於繼承原則
 */
public class ObjectAdapter implements IModernMount {
    
    private AncientMount ancientMount;  // 持有源物件參考
    // 甚至可持有多個源物件
    // private AnotherMount anotherMount;
    
    public ObjectAdapter(AncientMount ancientMount) {
        this.ancientMount = ancientMount;
    }
    
    @Override
    public void run() {
        // 委派給源物件
        ancientMount.run();
    }
    
    @Override
    public void fly() {
        System.out.println("物件適配器:施展飛行術,翱翔天際!");
    }
}

測試類別


public class AdapterDemo {
    public static void main(String[] args) {
        System.out.println("=== 類別適配器 ===");
        IModernMount classAdapter = new ClassAdapter();
        classAdapter.run();  // 繼承自 AncientMount
        classAdapter.fly();  // 適配器新增
        
        System.out.println("\n=== 物件適配器 ===");
        AncientMount ancient = new AncientMount();
        IModernMount objectAdapter = new ObjectAdapter(ancient);
        objectAdapter.run();  // 委派給 ancient
        objectAdapter.fly();  // 適配器新增
    }
}

執行結果


=== 類別適配器 ===
古代坐騎:在地上奔跑...
類別適配器:獲得飛行能力,騰空而起!

=== 物件適配器 ===
古代坐騎:在地上奔跑...
物件適配器:施展飛行術,翱翔天際!

深度比較

維度類別適配器物件適配器
實作關係繼承組合/委派
適配多個源不可(單繼承)可(持有多個參考)
覆寫源行為容易(Override)需重新實作或包裝
靈活度低(編譯期綁定)高(執行期可切換源物件)
符合設計原則違反「組合優於繼承」符合
適用場景源類別固定、需大量覆寫源類別多變、需執行期切換

進階變體

1. 雙向適配器

同時實作源介面與目標介面,可在兩種系統中互通:


public class TwoWayAdapter extends AncientMount implements IModernMount, IAncientMount {
    // 同時是古代坐騎也是現代坐騎
}

2. 預設適配器

提供介面的空實作,子類別只需覆寫需要的方法:


public abstract class MountAdapter implements IModernMount {
    public void run() { /* 預設實作 */ }
    public void fly() { /* 預設實作 */ }
}
// 使用時只覆寫 fly()
public class FlyOnlyAdapter extends MountAdapter {
    @Override public void fly() { /* 真實飛行邏輯 */ }
}

3. 適配器鏈

多層適配,逐步轉換介面:


// LegacySystem → Adapter1 → Adapter2 → ModernSystem

實務應用場景

1. 第三方庫整合


// 系統需求:ILogger
// 第三方:Log4jLogger, Slf4jLogger, JULLogger
public class Log4jAdapter implements ILogger {
    private Logger log4jLogger;
    public void log(String msg) { log4jLogger.info(msg); }
}

2. 資料庫驅動適配


// JDBC 本身就是適配器模式
// java.sql.Connection (Target) ← 各廠商驅動實作
// OracleConnection, MySQLConnection, PostgreSQLConnection (Adaptee)

3. 集合框架適配


// Arrays.asList() 將陣列適配為 List
List list = Arrays.asList("a", "b", "c");
// Collections.list() 將 Enumeration 適配為 Collection

4. Spring MVC HandlerAdapter


// Controller (Adaptee) → HandlerAdapter (Adapter) → DispatcherServlet (Client)
// SimpleControllerHandlerAdapter, HttpRequestHandlerAdapter, RequestMappingHandlerAdapter

最佳實踐建議

  1. 優先選擇物件適配器:符合組合優於繼承,彈性更高
  2. 介面隔離:目標介面應盡量精簡,避免「胖介面」導致適配器實作負擔過重
  3. 命名慣例:類別命名為 XXXAdapter,明確表達意圖
  4. 文件化:註解說明適配的是哪個類別、轉換了什麼介面、為什麼需要適配
  5. 避免過度使用:若能修改源碼直接實作目標介面更好;適配器適用於無法修改源碼(第三方、舊版)的情況

結語

適配器模式是結構型模式中的實用主力,透過介面轉換解決不兼容問題。理解類別與物件適配器的差異、掌握委派與繼承的權衡、識別適用場景,能有效整合舊系統、第三方庫與新架構,實現平滑演進。

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