軟體系統演進過程中,總會面臨「舊元件在新環境中生存」的問題:第三方庫升級介面變更、遺留系統整合、跨平台介面不匹配。適配器模式(Adapter Pattern)提供了解決方案:將一個類別的介面轉換成客戶期望的另一個介面,使原本因介面不相容而無法協作的類別能夠一起工作(GoF)。


| 維度 | 類別適配器(繼承) | 物件適配器(組合) |
|---|---|---|
| 實現機制 | 多重繼承:繼承 Adaptee、實作 Target | 組合:持有 Adaptee 參考、實作 Target |
| 耦合度 | 高:適配器與具體 Adaptee 緊耦合 | 低:適配器僅依賴 Adaptee 介面 |
| 覆寫行為 | 容易:可覆寫 Adaptee 的虛擬方法 | 困難:需建立 Adaptee 子類別再組合 |
| 適用性 | 單一 Adaptee、需覆寫行為 | 多個 Adaptee、需彈性組合、現代首選 |
WriteLog() 方法,有 DatabaseLog、FileLog 兩種實作WriteLog() 但簽名不同,無法修改原始碼(版權限制)ILogTarget.Write() 介面,不可修改
public class DatabaseLogAdapter : DatabaseLog, ILogTarget {
public void Write() => WriteLog(); // 直接呼叫繼承而來的方法
}
public class FileLogAdapter : FileLog, ILogTarget {
public void Write() => this.WriteLog();
}

致命缺陷:每種具體 Adaptee 都需一個適配器類別;違反單一職責(同時具備 Adaptee 與 Target 行為);無法適配 Adaptee 的子類別。
public class LogAdapter : ILogTarget {
private readonly LogAdaptee _adaptee;
public LogAdapter(LogAdaptee adaptee) { _adaptee = adaptee; }
public void Write() => _adaptee.WriteLog();
}

// 客戶端使用
ILogTarget dbLog = new LogAdapter(new DatabaseLog());
dbLog.Write("Logging Database...");
ILogTarget fileLog = new LogAdapter(new FileLog());
fileLog.Write("Logging File...");
優勢:單一適配器支援所有 Adaptee 及其子類別;鬆耦合;符合組合優於繼承原則。
public class MultiLogAdapter : ILogTarget {
private readonly LogAdaptee _adaptee1, _adaptee2;
public MultiLogAdapter(LogAdaptee a1, LogAdaptee a2) {
_adaptee1 = a1; _adaptee2 = a2;
}
public void Write() {
_adaptee1.WriteLog();
_adaptee2.WriteLog();
}
}
類別適配器因單一繼承限制,根本無法實現此類組合邏輯。
.NET 與 COM 物件模型截然不同,微軟以適配器模式建立雙向橋樑:
IUnknown、IDispatch 等標準 COM 介面,轉呼叫 .NET 物件
開發者無感知地使用 dynamic 或介面呼叫,適配器在背後處理所有複雜性。
IDataAdapter 介面,定義 Fill、Update 等統一操作SqlCommand、OracleCommand 等)SqlDataAdapter、OracleDataAdapter 等,將 Provider 特有 API 適配為統一介面應用程式僅依賴 DataSet 與 IDataAdapter,完全脫離具體資料庫類型。甚至可自訂 MyCustomDataAdapter 適配非標準資料源(CSV、Web API、快取系統等)。
MouseAdapter),子類別僅覆寫關心的方法以下情況請果斷使用適配器模式:
適配器模式是軟體演進的「萬能轉接頭」。它不創造新功能,而是消除介面不匹配的阻力,讓既有資產在新架構中繼續發光發熱。從 COM Interop 到 ADO.NET,從微服務閘道的協議轉換到前端 UI 元件庫的 Props 適配,其身影無處不在。掌握適配器,意味著你擁有了驾馭「異構系統整合」與「遺留系統現代化」的核心鑰匙。記住:好的適配器像空氣一樣透明,壞的適配器則像髒髒的管道阻礙流動。