1、引入需求背景
生活中手機充電需要的是5V 直流電,而電壓是20V 交流電。所以中間我們需要一個充電器將220V -> 5V。
引申一下,充電器本身相當於 Adapter,220V 交流電相當於 src (即被適配者),我們 的目 dst(即 目標)是 5V 直流電。
2、適配器模式的三種模式
- 類適配器模式
- 對象適配器模式
- 接口適配器模式
接下來我們通過三種模式來實現上述的需求。
2.1 類適配器模式
2.1.1 類圖分析
分析:有一個提供220V電壓的Voltage220V類,以及輸出5V電壓的接口,再來一個VoltageAdapter類去分別的繼承和實現,而Phone的方法只要去依賴接口就可以了。
2.1.2 代碼實現
public class Voltage220V {
public int output() {
return 220;
}
}
public interface IVoltage5V {
int output();
}
public class VoltageAdapter extends Voltage220V implements IVoltage5V {
@Override
public int output() {
int output = super.output();
System.out.println("輸出"+output);
System.out.println("轉換一下讓他變成5");
return 5;
}
}
public class Phone {
public void charging(IVoltage5V iVoltage5V) {
System.out.println(iVoltage5V.output()+"V充電");
}
}
public class Client {
public static void main(String[] args) {
Phone phone = new Phone();
phone.charging(new VoltageAdapter());
}
}
2.1.3 總結
- Java 是單繼承機制,所以類適配器需要繼承 src 類這一點算是一個缺點, 因爲這要求 dst 必須是接口,有一定侷限性;
- src 類的方法在 Adapter 中都會暴露出來,也增加了使用的成本。
- 由於其繼承了src類,所以它可以根據需求重寫src類的方法,使得Adapter的靈活性增強了。
2.2 對象適配器模式
2.2.1 類圖分析
分析:對象適配器模式的思路和類適配器模式基本上保持一致,不同在於對象適配器模式不是在繼承Voltage220V,而是採用聚合的方式,引入這個對象,降低耦合。
2.2.2 代碼實現
大致代碼和上述模式基本上保持一致,就是去掉繼承,改成組合。
public class VoltageAdapter implements IVoltage5V {
private Voltage220V voltage220V;
public VoltageAdapter(Voltage220V voltage220V) {
this.voltage220V = voltage220V;
}
@Override
public int output() {
int output = voltage220V.output();
System.out.println("輸出"+output);
System.out.println("轉換一下讓他變成5");
return 5;
}
}
public class Client {
public static void main(String[] args) {
Phone phone = new Phone();
phone.charging(new VoltageAdapter(new Voltage220V()));
}
}
2.2.3 總結
- 對象適配器和類適配器其實算是同一種思想,只不過實現方式不同。 根據合成複用原則,使用組合替代繼承, 所以它解決了類適配器必須繼承 src 的侷限性問題,也不再要求 dst 必須是接口。
- 使用成本更低,更靈活。
2.3 接口適配器模式
當接口裏方法很多,而不需要全部實現接口提供的方法時,可先設計一個抽象類實現接口,併爲該接口中每個方法提供一個默認實現(空方法),那麼該抽象類的子類可有選擇地覆蓋父類的某些方法來實現需求。
2.3.1 代碼實現
public interface IVoltageAdapter {
void m1();
void m2();
void m3();
void m4();
}
public abstract class AbstractVoltage implements IVoltageAdapter{
@Override
public void m1() {
}
@Override
public void m2() {
}
@Override
public void m3() {
}
@Override
public void m4() {
}
}
我們用到接口裏的哪個方法就去覆蓋某一個方法。
public class Phone {
public void charging() {
//只需要去覆蓋我們需要使用的接口方法
IVoltageAdapter adapter = new AbstractVoltage(){
@Override
public void m1() {
super.m1();
}
};
adapter.m1();
}
public static void main(String[] args) {
Phone phone = new Phone();
phone.charging();
}
}