1、引入需求背景
生活中手机充电需要的是5V 直流电,而电压是20V 交流电。所以中间我们需要一个充电器将220V -> 5V。
引申一下,充电器本身相当于 Adapter,220V 交流电相当于 src (即被适配者),我们 的目 dst(即 目标)是 5V 直流电。
2、适配器模式的三种模式
- 类适配器模式
- 对象适配器模式
- 接口适配器模式
接下来我们通过三种模式来实现上述的需求。
2.1 类适配器模式
2.1.1 类图分析
分析:有一个提供220V电压的Voltage220V类,以及输出5V电压的接口,再来一个VoltageAdapter类去分别的继承和实现,而Phone的方法只要去依赖接口就可以了。
2.1.2 代码实现
public class Voltage220V {
public int output() {
return 220;
}
}
public interface IVoltage5V {
int output();
}
public class VoltageAdapter extends Voltage220V implements IVoltage5V {
@Override
public int output() {
int output = super.output();
System.out.println("输出"+output);
System.out.println("转换一下让他变成5");
return 5;
}
}
public class Phone {
public void charging(IVoltage5V iVoltage5V) {
System.out.println(iVoltage5V.output()+"V充电");
}
}
public class Client {
public static void main(String[] args) {
Phone phone = new Phone();
phone.charging(new VoltageAdapter());
}
}
2.1.3 总结
- Java 是单继承机制,所以类适配器需要继承 src 类这一点算是一个缺点, 因为这要求 dst 必须是接口,有一定局限性;
- src 类的方法在 Adapter 中都会暴露出来,也增加了使用的成本。
- 由于其继承了src类,所以它可以根据需求重写src类的方法,使得Adapter的灵活性增强了。
2.2 对象适配器模式
2.2.1 类图分析
分析:对象适配器模式的思路和类适配器模式基本上保持一致,不同在于对象适配器模式不是在继承Voltage220V,而是采用聚合的方式,引入这个对象,降低耦合。
2.2.2 代码实现
大致代码和上述模式基本上保持一致,就是去掉继承,改成组合。
public class VoltageAdapter implements IVoltage5V {
private Voltage220V voltage220V;
public VoltageAdapter(Voltage220V voltage220V) {
this.voltage220V = voltage220V;
}
@Override
public int output() {
int output = voltage220V.output();
System.out.println("输出"+output);
System.out.println("转换一下让他变成5");
return 5;
}
}
public class Client {
public static void main(String[] args) {
Phone phone = new Phone();
phone.charging(new VoltageAdapter(new Voltage220V()));
}
}
2.2.3 总结
- 对象适配器和类适配器其实算是同一种思想,只不过实现方式不同。 根据合成复用原则,使用组合替代继承, 所以它解决了类适配器必须继承 src 的局限性问题,也不再要求 dst 必须是接口。
- 使用成本更低,更灵活。
2.3 接口适配器模式
当接口里方法很多,而不需要全部实现接口提供的方法时,可先设计一个抽象类实现接口,并为该接口中每个方法提供一个默认实现(空方法),那么该抽象类的子类可有选择地覆盖父类的某些方法来实现需求。
2.3.1 代码实现
public interface IVoltageAdapter {
void m1();
void m2();
void m3();
void m4();
}
public abstract class AbstractVoltage implements IVoltageAdapter{
@Override
public void m1() {
}
@Override
public void m2() {
}
@Override
public void m3() {
}
@Override
public void m4() {
}
}
我们用到接口里的哪个方法就去覆盖某一个方法。
public class Phone {
public void charging() {
//只需要去覆盖我们需要使用的接口方法
IVoltageAdapter adapter = new AbstractVoltage(){
@Override
public void m1() {
super.m1();
}
};
adapter.m1();
}
public static void main(String[] args) {
Phone phone = new Phone();
phone.charging();
}
}