适配器模式(Adapter Rattern)将某个类的接口转换成客户端期望的另一个接口表示,主的目的是兼容性,让原本因接口不匹配不能一起工作的两个类可以协同工作。其别名为包装器(Wrapper)。类比,U盘插个转换头可用与手机type-c接口相连接;或者是使用多功能转换插头,实现三孔插头与两孔插座相连。
适配器模式将一个类的接口转换成另一种接口,让原本接口不兼容的类可以兼容。从用户的角度看不到被适配者,是解耦的;用户调用适配器转化出来的目标接口方法,适配器再调用被适配者的相关接口方法;用户收到反馈结果,感觉只是和目标接口交互。
适配器模式属于结构型模式,主要分为三类:类适配器模式、对象适配器模式、接口适配器模式。
Adapter类,通过继承src类,实现dst类接口,完成src->dst的适配。
缺点:Java是单继承机制,所以类适配器需要继承src类;要求dst必须是接口,有一定局限性;src类的方法在Adapter中都会暴露出来,也增加了使用的成本。
优点:由于其继承了src类,所以它可以根据需求重写src类的方法,使得Adapter的灵活性增强了。
以充电器转换电压为例
Voltage220V类,表示被适配类,输出220v电压
//被适配类
public class Voltage220V {
//输出220V的电压
public int output220V(){
int src = 220;
System.out.println("电压="+src+"伏");
return src;
}
}
IVoltage5V接口,表示适配接口,抽象输出5v的方法
//适配接口
public interface IVoltage5V {
public int output5V();
}
VoltageAdapter类,表示适配器类,继承被适配类,又实现适配接口,实现220v->5v转换
public class VoltageAdapter extends Voltage220V implements IVoltage5V{
@Override
public int output5V() {
int srcV = output220V();//获取220v
int dstV = srcV / 44;//转成5v
return dstV;
}
}
Phone类,实现充电方法
public class Phone {
//充电
public void charging(IVoltage5V iVoltage5V){
if(iVoltage5V.output5V()==5){
System.out.println("电压为5v,可以充电");
}else if(iVoltage5V.output5V()>5){
System.out.println("电压大于5v,无法充电");
}
}
}
Client类,客户端
public class Client {
public static void main(String[] args) {
Phone phone = new Phone();
phone.charging(new VoltageAdapter());
}
}
输出结果
基本思路和类的适配器模式相同,只是将Adapter类作修改,不是继承src类,而是持有src类的实例,以解决兼容性的问题。即:持有src类,实现dst类接口,完成src->dst的适配。根据“合成复用原则”,在系统中尽量使用关联关系来替代继承关系。对象适配器模式是适配器模式常用的一种。
仍以充电器转换电压为例,只需改变适配器类和客户端,其他不变
Voltage220V类,表示被适配类,输出220v电压
//被适配类
public class Voltage220V {
//输出220V的电压
public int output220V(){
int src = 220;
System.out.println("电压="+src+"伏");
return src;
}
}
IVoltage5V接口,表示适配接口,抽象输出5v的方法
//适配接口
public interface IVoltage5V {
public int output5V();
}
VoltageAdapter类,表示适配器类,实现适配接口,通过聚合关系持有Voltage220V类而不再是继承,实现220v->5v转换
public class VoltageAdapter implements IVoltage5V {
private Voltage220V voltage220V;
//根据构造器,传入一个Voltage220V,聚合关系
public VoltageAdapter(Voltage220V voltage220V) {
this.voltage220V = voltage220V;
}
@Override
public int output5V() {
int dstV = 0;
if (null != voltage220V) {
int srcV = voltage220V.output220V();//获取220v
dstV = srcV / 44;//转成5v
}
return dstV;
}
}
Phone类,实现充电方法
public class Phone {
//充电
public void charging(IVoltage5V iVoltage5V){
if(iVoltage5V.output5V()==5){
System.out.println("电压为5v,可以充电");
}else if(iVoltage5V.output5V()>5){
System.out.println("电压大于5v,无法充电");
}
}
}
Client类,客户端
public class Client {
public static void main(String[] args) {
System.out.println("对象适配器模式");
Phone phone = new Phone();
phone.charging(new VoltageAdapter(new Voltage220V()));
}
}
输出结果
又称适配器模式(Default Adapter Pattern)或缺省适配器模式。当不需要全部实现接口提供的方法时,可先设计一个抽象类实现接口,并为该接口中每个方法提供一个默认实现(空方法),那么该抽象类的子类可有选择地覆盖父类的某些方法来实现需求。适用于一个接口不想使用其所有的方法的情况。
接口Interface4,表示提供4个方法
public interface Interface4 {
public void m1();
public void m2();
public void m3();
public void m4();
}
AbsAdapter抽象类,实现接口,并使接口每个方法默认空实现
public abstract class AbsAdapter implements Interface4{
//默认实现
@Override
public void m1() {
}
@Override
public void m2() {
}
@Override
public void m3() {
}
@Override
public void m4() {
}
}
Client类,通过匿名内部类的方式,有选择地覆盖父类的某些方法来实现需求
public class Client {
public static void main(String[] args) {
AbsAdapter absAdapter = new AbsAdapter() {
@Override
public void m1() {
System.out.println("只想使用m1的方法,只需覆盖m1的方法");
}
};
absAdapter.m1();
}
}
输出结果
类适配器: 以类给到,在Adapter里,就是将src当做类,继承
对象适配器: 以对象给到,在Adapter里,将src作为一个对象,持有
接口适配器: 以接口给到,在Adapter里,将src作为一个接口,实现
Adapter模式最大的作用还是将原本不兼容的接口融合在一起工作。