前面两篇博客写了详解单例模式六种写法的优缺点和详解原型模式的浅复制(浅拷贝)和深复制(深拷贝), 感觉效果还不错。
下面来说一下适配器模式, 说起适配器模式不妨举个例子 手机充电器, 我们手机充电的时候会把220V的电压转为5V(现在手机基本上都是5V), 这就和我们要说的适配器模式很像, 下面围绕着这个例子来写一下代码
- 首先我们先写一个插孔(提供220V的电压)
public class Voltage220V {
public int output220V() {
int src = 220;
return src;
}
}
- 在写一个适配的接口, 提供一个转换的方法, 然后去实现它
public interface IVoltage5V {
public int output5V();
}
public class VoltageAdapter extends Voltage220V implements IVoltage5V {
@Override
public int output5V() {
int srcV = output220V();
int dstV = srcV / 44 ;
return dstV;
}
}
- 然后写一个手机类, 手机不能直接使用220V的电压, 只能通过适配器转为5V去使用
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, 不能充电~~");
}
}
}
- 客户端
public static void main(String[] args) {
Phone phone = new Phone();
phone.charging(new VoltageAdapter());
}
优点
- 适配器继承了被适配的类(Voltage220V ), 使得适配器可以重写被适配的类(Voltage220V )的方法, 提高了适配器的灵活性
缺点
- 因为java是单继承, 适配器继承了被适配的类(Voltage220V ), 所以适配器只能是接口。
- 被适配的类(Voltage220V )的方法在适配器中都会暴露出来, 增加了使用成本
- 被适配的类(Voltage220V)、手机类(Phone)、适配器接口(IVoltage5V) 这三个都不变
- 核心的变化是适配器类(VoltageAdapter), 从继承关系变成了聚合关系
public class VoltageAdapter implements IVoltage5V {
private Voltage220V voltage220V;
public VoltageAdapter(Voltage220V voltage220v) {
this.voltage220V = voltage220v;
}
@Override
public int output5V() {
int dst = 0;
if(null != voltage220V) {
int src = voltage220V.output220V();
dst = src / 44;
System.out.println("适配完成,输出的电压为=" + dst);
}
return dst;
}
}
- 客户端有一点小小的变动, 因为我们适配的是对象, 所以我们要把对象传进去
public static void main(String[] args) {
Phone phone = new Phone();
phone.charging(new VoltageAdapter(new Voltage220V()));
}
优点
- 利用合成复用原则, 使用聚合代替了继承
- 解决了类适配器必须继承被适配的类(Voltage220V )
- 成本低, 更灵活
缺点
- 要全部实现接口里的方法(如果接口里还有一个转为2V的方法, 也要实现)
- 在类适配器原有的基础上我们在适配器接口(IVoltage5V)在加一个方法IVoltage2V
public interface IVoltage5V {
public int output5V();
public int output2V();
}
- 增加一个抽象类, 默认实现IVoltage5V 接口(空方法)
public abstract class AbsAdapter implements IVoltage5V {
@Override
public int output5V() {
return 0;
}
@Override
public int output2V() {
return 0;
}
}
- 适配器类(VoltageAdapter)继承抽象类, 只需要重写自己需要的方法
public class VoltageAdapter extends AbsAdapter {
private Voltage220V voltage220V;
public VoltageAdapter(Voltage220V voltage220v) {
this.voltage220V = voltage220v;
}
@Override
public int output5V() {
int dst = 0;
if(null != voltage220V) {
int src = voltage220V.output220V();
dst = src / 44;
}
return dst;
}
}
优点
三种适配器各有利弊, 还是要在实际开发中根据实际情况选择。对象适配器和接口适配器和相似, 只能说是两种写法, 并不能说谁可以代替谁。如对本文有疑惑, 请留言一起交流学习!