適配器模式將一個類的介面轉換成客戶期望的另一個介面,讓原本不相容的類能夠協同工作。本文詳細對比兩種實作形式:類適配器(繼承)與 物件適配器(組合),並提供完整代碼示例。
| 維度 | 類適配器 | 物件適配器 |
|---|---|---|
| 核心關係 | 繼承 Source 類 | 組合 Source 物件 |
| 實作介面 | implements Target | implements Target |
| 適配範圍 | 單一 Source 類 | 可適配多個 Source 物件 |
| 靈活性 | 較低(靜態綁定) | 較高(動態組合) |
| 覆寫行為 | 可覆寫 Source 方法 | 僅能委派,難以覆寫 |
舊系統:所有坐騎只能 run()(跑)
新需求:坐騎需同時支援 run() 與 fly()(飛)
目標介面:ITarget { run(); fly(); }
// 來源類:舊系統坐騎
public class Sources {
public void run() { System.out.println("run"); }
}
// 目標介面:新需求
public interface ITarget {
void run();
void fly();
}
// 類適配器:繼承 Sources,實作 ITarget
public class Adapter extends Sources implements ITarget {
@Override
public void fly() { System.out.println("fly"); }
// run() 直接繼承自 Sources
}
適用場景:單一來源類、需覆寫部分方法、編譯期確定適配關係。
// 來源物件:可能有多種動物
public class Animal {
public void run() { System.out.println("run"); }
}
// 目標介面同前
// 物件適配器:組合 Animal,實作 ITarget
public class Adapter implements ITarget {
private Animal animal; // 可擴展為多個來源物件
public Adapter(Animal animal) { this.animal = animal; }
@Override
public void fly() { System.out.println("fly"); } // 新增行為
@Override
public void run() { animal.run(); } // 委派來源物件
}
適用場景:多來源類、運行期動態切換來源、不想建立繼承關係。
public class TwoWayAdapter implements ITarget, Sources {
private Animal animal;
private Sources source;
public TwoWayAdapter(Animal a) { this.animal = a; }
public TwoWayAdapter(Sources s) { this.source = s; }
@Override public void run() {
if (animal != null) animal.run();
else if (source != null) source.run();
}
@Override public void fly() { System.out.println("fly"); }
}
Adapter 結尾,如 JdbcTemplateAdapter適配器模式是結構型模式中最實用的模式之一。類適配器透過繼承實現簡單但耦合度高;物件適配器透過組合實現靈活,符合「組合優於繼承」原則。現代開發中,物件適配器配合依賴注入框架(如 Spring)使用更為普遍,能夠優雅解決介面不兼容問題。