适配器模式(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单继承,有一定局限性)