適配器模式(wrapper包裝者模式):將一個接口轉換成用戶所需要的接口,使相互不兼容的接口一起工作。
例子:筆記本、筆記本電源適配器、交流電。 在各個國家的交流電有些是不相同的,如220V、110V,而筆記本電腦充電電壓基本爲20V(以我的Y7000爲例),是不能直接接入充電的,因此筆記本都配置了一個電源適配器。這就用到了適配器模式
適配器模式中常用的角色
- Target(目標角色,筆記本20V直流電):目標接口或者類 DC20Tage及其實現類
- Adapter(適配器,電源適配器):將原角色適配爲目標角色 DC20Adapter及其實現類
- Adaptee(原角色,110V,220V交流電):需要適配的類 ACAdaptee及其實現類
一、UML類圖
二、代碼
1.Target 目標
package adapter;
public interface DC20Taget {
int outputDC();
}
package adapter;
/**
* 目標爲生產出筆記本所需要的電
*/
public class LoptopTaget implements DC20Taget {
private int voltage;
public LoptopTaget(int voltage) {
this.voltage = voltage;
}
public int outputDC() {
return voltage;
}
}
2.Adaptee 原代碼
package adapter;
public interface ACAdaptee {
int outputAC();
}
package adapter;
/**
* 需要適配的110V電源
*/
public class AmericaACAdaptee implements ACAdaptee {
private final int voltage = 110;
public int outputAC() {
return voltage;
}
}
package adapter;
/**
* 需要適配的220V電源
*/
public class ChinaACAdaptee implements ACAdaptee {
private final int voltage = 220;
public int outputAC() {
return voltage;
}
}
3.Adapter 適配器
package adapter;
public interface DC20Adapter {
boolean support(ACAdaptee ac);
DC20Taget outputDC20();
}
package adapter;
/**
* 110V電源適配器,轉換爲筆記本需要的電源並且返回
*/
public class AmericaPowerAdapter implements DC20Adapter {
private final int voltage = 110;
private ACAdaptee ac;
public boolean support(ACAdaptee ac) {
boolean flag = voltage == ac.outputAC();
this.ac = flag ? ac: this.ac ;
return flag;
}
public DC20Taget outputDC20() {
int inputVoltage = ac.outputAC();
int out = ((Double)(inputVoltage/5.5)).intValue();
System.out.println("使用AmericaPowerAdapter,輸入電壓"+inputVoltage+"輸出電壓"+out);
DC20Taget dc20 = new LoptopTaget(out);
return dc20;
}
}
package adapter;
/**
* 220V電源適配器,返回筆記本所需要的電源
*/
public class ChinaPowerAdapter implements DC20Adapter {
private final int voltage = 220;
private ACAdaptee ac;
public boolean support(ACAdaptee ac) {
boolean flag = voltage == ac.outputAC();
this.ac = flag ? ac: this.ac;
return flag;
}
public DC20Taget outputDC20() {
int inputVoltage = ac.outputAC();
int out = inputVoltage/11;
System.out.println("使用ChinaPowerAdapter,輸入電壓"+inputVoltage+"輸出電壓"+out);
DC20Taget dc20 = new LoptopTaget(out);
return dc20;
}
}
4.測試代碼
package adapter;
import java.util.LinkedList;
import java.util.List;
public class Client {
//需要的適配器組
private List<DC20Adapter> adapters = new LinkedList<DC20Adapter>();
public Client(){
this.adapters.add(new ChinaPowerAdapter());
this.adapters.add(new AmericaPowerAdapter());
}
//返回所需要的適配器
public DC20Adapter getAdapter(ACAdaptee ac) throws Exception {
DC20Adapter dc20 = null;
for(DC20Adapter adapter:this.adapters){
if(adapter.support(ac)){
dc20 = adapter;
break;
}
}
if(dc20 == null){
throw new Exception("沒找到適配器");
}
return dc20;
}
public static void main(String[] args) throws Exception {
Client client = new Client();
ACAdaptee ac220 = new ChinaACAdaptee();
DC20Adapter adapter = client.getAdapter(ac220);
DC20Taget dc20Taget = adapter.outputDC20();
ACAdaptee ac110 = new AmericaACAdaptee();
adapter = client.getAdapter(ac110);
DC20Taget dc20Taget1 = adapter.outputDC20();
System.out.println("ChinaACAdaptee類適配結果"+dc20Taget.outputDC());
System.out.println("AmericaACAdaptee類適配結果"+dc20Taget1.outputDC());
}
}
三、總結
適配器模式可以在不改動原有代碼的情況下,滿足新的需求,符合面向對象設計原則對修改關閉對擴展開放。
適配器模式在SpringMVC 中有很有些的事例,可以參考學習(待源碼跟蹤..........................)。
適配器模式,分爲對象適配器模式、類適配器模式,
- 對象適配器模式:需要適配的對象在適配器類中以組合的方式存在(使用方便靈活)
- 類適配器模式:需要適配的對象是適配器的父類(java單繼承,有一定侷限性)