適配器的概念可以通過下圖進行說明,
生活中最常見的例子就是電壓轉換插頭,通過放置在電源與充電設備之間,能夠使得兩個原本不能一同使用的物品配合使用。
使用適配器模式的情形可以總結爲,
- 現有的類或接口不能滿足要求,且不能對現有的類和接口代碼進行改動
1.組成角色
適配器模式,根據適配器類與適配者類的關係不同,適配器模式可分爲對象適配器和類適配器兩種。
- 對象適配器模式中,適配器和適配者之間是關聯關係
- 類適配器模式中,適配器和適配者之間是繼承關係
適配器的組成如下圖,
舉個例子,如果想讓直流 12v 的筆記本電腦工作在交流 220v 的電源下,就必須要一個電源適配器,該適配器的作用就是將 220v 的 AC 交流轉爲 12v 的 DC 直流。
角色 | 說明 |
---|---|
目標(target) | 該角色定義把其它類轉換爲何種接口,也就是期望接口,可以是一個抽象類或接口,也可以是具體類。以上文中筆記本電腦爲例,即指讓筆記本正常工作的直流 12v 電源 |
適配器(Adapter) | 適配器可以調用另一個接口,作爲一個轉換器,對 Adaptee 和 Target 進行適配,適配器類是適配器模式的核心,通常都是一個具體的類。以上文中筆記本電腦爲例,即指電源適配器 |
源角色(被適配 Adaptee ) | 已經存在的、運行良好的類或對象,經過適配器角色的包裝,它會成爲一個嶄新的角色。以上文中筆記本電腦爲例,即指 220v 的 AC 電源 |
請求者(Client) | 該角色負責使用 Target 定義的方法進行具體處理,以上文中筆記本電腦爲例,即指使用 12v 電源驅動的筆記本電腦。 |
對上方圖表內容進行概括,Adapter 就是一個在 Client 中使用 Target 定義的接口來使用 Adaptee 角色(調用 Adaptee 中的方法)的存在。
2.代碼實現
類適配器
適配器Adapter與適配者之間使用繼承關係,
- 定義Target接口
public Interface Target {
public abstract void targetMethod1();
public abstract void targetMethod2();
}
- 定義適配者
public class Adaptee {
public void methodA() {
System.out.println("Adaptee methodA invoked.");
}
public void methodB() {
System.out.println("Adaptee methodB invoked.");
}
}
- 定義適配器
public class Adapter extends Adaptee implements Target{
@Override
public void targetMethod1() {
System.out.println("Adapter targetMethod1 inkoked.");
methodA();
}
@Override
public void targetMethod2() {
System.out.println("Adapter targetMethod2 inkoked.");
methodB();
}
}
- Client使用適配器
public class Main {
public static void main(String[] args) {
// 通過Adapter繼承Adaptee實現了Adaptee角色的調用
Target target = new Adapter();
target.targetMethod1();
target.targetMethod2();
}
}
對象適配器
對象適配器使用委託的方式,即適配器中包含適配者的實例對象,
- 定義Target類
注意此處不再是接口,
public abstract class Target {
public abstract void targetMethod1();
public abstract void targetMethod2();
}
- 定義適配者
代碼與類適配器中的代碼相同 - 定義適配器
public class Adapter extends Target {
private Adaptee adaptee;
public Adapter() {
this.adaptee = new Adaptee(); // 委託
}
@Override
public void targetMethod1() {
System.out.println("Adapter targetMethod1 inkoked.");
adaptee.methodA();
}
@Override
public void targetMethod2() {
System.out.println("Adapter targetMethod2 inkoked.");
adaptee.methodB();
}
}
- 使用適配器
public static void main(String[] args) {
// 通過Adapter使用委託,實現了Adaptee角色的調用
Target target = new Adapter();
target.targetMethod1();
target.targetMethod2();
}
3.優缺點
優點:
- 將目標類和適配者解耦,引入適配器實現以Target的方式使用Adaptee,無需修改原結構
- 同一個Adaptee可以在多個不同的系統中複用
- 將兩個原本不相關聯的類關聯在一起
缺點:
- Java和C#等語言不支持多繼承,一次最多隻能適配一個Adaptee