适配器模式
- 适配器模式将某个类的接口转换成客户端期望的另一个接口表示,主要目的是兼容性,让原本因接口不匹配不能在一起工作的两个类可以协同工作。其别名为包装器
- 适配器模式属于结构型模式
- 主要分为三类:类适配器模式、对象适配器模式和接口适配器模式
工作原理
- 适配器模式:将一个类的接口转换成另一种接口,让原本接口不兼容的类可以兼容
- 从用户的角度看不到被适配者,是解耦的
- 用户调用适配器转化出来的目标接口方法,适配器再调用被适配者的相关接口方法
- 用户收到反馈结果,感觉只是和目标接口交互
类适配器
adapter类,通过继承src类,实现dst类接口,完成src->dst的适配
src类
//被适配的类
public class Voltage220v{
//输出220v电压
public int output220v(){
int src = 220;
System.out.println("电压="+src+"伏");
return src;
}
}
dst类
//适配接口
public interface IVoltage5V{
public int output5v();
}
adapter类
//适配器
public class VoltageAdapter extends Voltage220v implements IVoltage5v{
@Overide
public int output5v(){
//获取220v电压
int src220v = output220v();
//转换成5v
int dst5v = src220v / 44;
return dst5v;
}
}
使用类:
public class Phone{
//充电
public void charging(IVoltage5v iVoltage5v){
if(iVoltage5v.output5v()==5){
System.out.println("可以充电");
}
}
}
测试:
Phone phone = new Phone();
phone.charging(new VoltageAdapter());
注意事项:
- java是单继承机制,所以类适配器需要继承src类这一点是一个缺点,因为者要求dst必须是接口,有一定局限性
- src类的方法再adapter中都会暴露出来,也增加了使用成本
- 由于其继承了src类,所以它可以根据需求重写src类的方法,使得adapter的灵活性增强了
对象适配器
- 基本思路和类的适配器模式相同,只是将adapter类作修改,不是继承src类,而且持有src类的实例,已解决兼容性问题。即:持有src类,实现dst类接口,完成src->dst的适配
- 根据合成复用原则,再系统中尽量使用关联关系来替代继承关系
adapter:
//适配器
public class VoltageAdapter implements IVoltage5v{
//持有src对象,而不是继承(聚合关系)
private Voltage220v voltage220v;
public VoltageAdapter(Voltage220v voltage220v){
this.voltage220v = voltage220v;
}
@Overide
public int output5v(){
//获取220v电压
int src220v = voltage220v.output220v();
//转换成5v
int dst5v = src220v / 44;
return dst5v;
}
}
注意事项:
-
对象适配器和类适配器其实算是同一种思想,只不过实现方式不同。
根据合成复用原则,使用组合替代继承,所以它解决了类适配器必须继承src的局限性问题,也不要去dst必须是接口
-
使用成本更低,更灵活
接口适配器
- 也叫缺省适配器模式
- 当不需要全部实现接口提供的方法时,可以先设计一个抽象类实现接口,并为该接口中每个方法提供一个默认实现(空方法),那么该抽象类的子类可有选择的覆盖父类的某些方法来实现需求
- 适用于一个接口不想使用其所有的方法的情况
接口:
public interface MyInterface{
void fun1();
void fun2();
void fun3();
void fun4();
}
抽象类(适配器):
//将接口中的方法进行空实现
public abstract class AbsAdapter implements MyInterface{
@Overide
public void fun1(){}
@Overide
public void fun2(){}
@Overide
public void fun3(){}
@Overide
public void fun4(){}
}
使用:
public class MyImpl extends AbsAdapter{
//只覆盖自己关系的方法
@Overide
public void fun2(){
...
}
}
总结
- 三种命名方式:是根据src(被适配的类)是以怎样的形式给到adapter的(在adapter中的形式)
- 类适配器:以类给到adapter里,就是将src当作类,继承
- 对象适配器:以对象给到adapter里,将src作为一个对象,持有
- 接口适配器:以接口给到adapter里,将src作为一个接口,实现
- 适配器模式最大的作用还是将原本不兼容的接口融合在一起工作