-
定义:适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
三种适配器:类的适配器模式、对象的适配器模式
1 适配器模式之类适配器模式
实现方式:让Adapter继承Adaptee类,然后再实现Target接口,来实现适配器功能
- Adaptee:适配者类,它是需要被访问的、需要被适配的组件. AC220V
- Target:目标接口,当前系统业务所使用的接口,可以是抽象类或接口. DC5V
- Adapter:适配器类,通过继承和实现目标接口,让客户端按照目标接口的方法访问适配者
- Client:客户端,适配器的使用者
实例:手机充电需要将220V的交流电转化为手机锂电池需要的5V直流电。使用电源适配器,将 AC220v ——> DC5V。
类图
代码:
/**
* 源角色(Adaptee):现在需要适配的接口。
*/
public class AC220 {
/**
* 输出220V交流电
*
* @return
*/
public int output220V() {
int output = 220;
return output;
}
}
/**
* 目标角色(Target):这就是所期待得到的接口。
* 注意:由于这里讨论的是类适配器模式,因此目标不可以是类。
*/
public interface DC5 {
/**
* 输出5V直流电(期待得到的接口)
*
* @return
*/
int output5V();
}
/**
* 类适配器
* 适配器类是本模式的核心。适配器把源接口转换成目标接口。显然,这一角色不可以是接口,而必须是具体类。
*/
public class PowerAdapter extends AC220 implements DC5 {
/**
* 输出5V直流电
*
* @return
*/
@Override
public int output5V() {
int output = output220V();
return (output / 44);
}
}
/**
* 测试类适配器
*/
public class TestClassAdapter {
public static void main(String[] args) {
DC5 dc5 = new PowerAdapter();
System.out.println("输出电流:" + dc5.output5V() + "V");
}
}
优点:由于Adapter继承了Adaptee类,所以它可以根据需求重写Adaptee类的方法,使得Adapter的灵活性增强了。
缺点:因为java单继承的缘故,Target类==必须是接口==,以便于Adapter去继承Adaptee并实现Target,完成适配的功能,但这样就导致了Adapter里暴露了Adaptee类的方法,使用起来的成本就增加了。
2 适配器模式之对象适配器模式
实现方式:让Adapter持有Adaptee类的实例,然后再实现Target接口,以这种持有对象的方式来实现适配器功能。
- `Adaptee`:适配者类,它是需要被访问的、需要被适配的组件
- `Target`:目标接口,当前系统业务所使用的接口,可以是抽象类或接口
- `Adapter`:适配器类,通过聚合和实现目标接口,让客户端按照目标接口的方法访问适配者
- `Client`:客户端,适配器的使用者
实例:手机充电需要将220V的交流电转化为手机锂电池需要的5V直流电。使用电源适配器,将 AC220v ——> DC5V。
类图
代码
/**
* 源角色(Adaptee):现在需要适配的接口。
*/
public class AC220 {
/**
* 输出220V交流电
*
* @return
*/
public int output220V() {
int output = 220;
return output;
}
}
/**
* 目标角色(Target):这就是所期待得到的接口。
*/
public interface DC5 {
/**
* 输出5V直流电(期待得到的接口)
*
* @return
*/
int output5V();
}
/**
* 对象适配器
*/
public class PowerAdapter implements DC5 {
private AC220 ac220;
public PowerAdapter(AC220 ac220) {
this.ac220 = ac220;
}
/**
* 输出5V直流电
*
* @return
*/
@Override
public int output5V() {
int output = this.ac220.output220V();
return (output / 44);
}
}
/**
* 测试对象适配器
*/
public class TestObjectAdapter {
public static void main(String[] args) {
AC220 ac220 = new AC220();
PowerAdapter powerAdapter = new PowerAdapter(ac220);
System.out.println("输出电流:" + powerAdapter.output5V() + "V");
}
}
优点:根据合成复用原则,使用组合替代继承, 所以它解决了类适配器必须继承Adaptee的局限性问题,也不再要求Target必须是接口。使用成本更低,更灵活。