目录
一、基础概念
二、UML类图
1、类适配器
2、对象适配器
三、角色设计
四、代码实现
案例一
案例二
五、总结
将一个类的接口转换为另一个接口,使得原本由于接口不兼容的类进行兼容。
适配器模式主要分为类适配器模式和对象适配器模式,前者类适配器模式之间的耦合度比后者更高,所以更推荐使用对象适配器。
角色 | 描述 |
---|---|
目标接口 | 客户所期待的接口 |
适配者类 | 它是被访问和适配的现存组件库中的组件接口 |
适配器 | 通过包装一个需要适配的对象,把原接口转换为目标接口 |
假设一个手机只支持5W的充电功率,如果充电功率大于5W,则不能进行充电,那我们就需要对大于5W的充电功率进行向下兼容适配,以下是代码实现过程。
定义一个5W的目标接口Target:
public interface Power5WTarget {
public int outPut5W();
}
这是我们需要适配的类Adaptee:
public class Power60WAdaptee {
public int outPut60W(){
System.out.println("充电功率60W");
return 60;
}
}
采用类适配器进行适配:
public class ClassAdapter extends Power60WAdaptee implements Power5WTarget {
@Override
public int outPut5W() {
int power = super.outPut60W();
return power/12;
}
}
采用对象适配器进行适配:
public class ObjAdapter implements Power5WTarget {
private Power60WAdaptee power60WAdaptee;
public ObjAdapter(Power60WAdaptee power60WAdaptee){
this.power60WAdaptee = power60WAdaptee;
}
@Override
public int outPut5W() {
int power = this.power60WAdaptee.outPut60W();
return power/12;
}
}
新建一个手机类:
public class Phone {
public void charging(Power5WTarget power5WTarget) {
if(power5WTarget.outPut5W() == 5) {
System.out.println("电压符合标准,允许充电!");
} else if (power5WTarget.outPut5W() > 5) {
System.out.println("电压过大,禁止充电!");
}
}
}
客户端:
public class Client {
public static void main(String[] args) {
Phone phone = new Phone();
phone.charging(new ClassAdapter());
phone.charging(new ObjAdapter(new Power60WAdaptee()));
}
}
运行结果如下:
假设由如下场景:由一个接口只支持USB接口进行手机充电,现在来了个无线充电的手机也想通过USB进行充电,这边我们就需要为无线充电做一个适配转换。
目标接口,客户所期待的Usb接口:
public interface UsbTarget {
void usb();
}
要适配的类或适配者类:
public class WirelessAdaptee {
public void wireless(){
System.out.println("无线充电...");
}
}
类适配器,通过包装一个需要适配的对象,把原接口转换成目标接口:
public class ClassAdapter extends WirelessAdaptee implements UsbTarget{
@Override
public void usb() {
super.wireless();
System.out.println("wireless -> usb");
}
}
对象适配器,通过包装一个需要适配的对象,把原接口转换成目标接口:
public class ObjAdapter implements UsbTarget{
private WirelessAdaptee wirelessAdaptee;
public ObjAdapter(WirelessAdaptee wirelessAdaptee){
this.wirelessAdaptee = wirelessAdaptee;
}
@Override
public void usb() {
this.wirelessAdaptee.wireless();
System.out.println("wireless -> usb");
}
}
客户端:
public class Client {
public static void main(String[] args) {
// 类适配器
ClassAdapter classAdapter = new ClassAdapter();
classAdapter.usb();
// 对象适配器
ObjAdapter objAdapter = new ObjAdapter(new WirelessAdaptee());
objAdapter.usb();
}
}
运行结果如下:
类适配器和对象适配器区别:
类适配器:单继承,一次最多只能适配一个适配者类
对象适配器:可以把多个不同的适配者适配到同一个目标
优点:
1、增加了类的透明性和兼容性。
2、提高了程序的灵活性,降低了耦合度。
3、优秀的适配器可以把不匹配的接口转换为友好的接口。
4、符合开闭原则。
缺点:
1、过多地使用适配器,会让系统的逻辑复杂化。
2、适配器又增加了一个适配层,有一定额外消耗。
应用场景:
1、希望复用一些现存的类,但是接口不匹配的情况。
2、抽象类接口需要优化,但又不能直接修改的场景。
3、统一多个类的接口到一个接口中。
4、系统移植需要适配不同接口的场景。
符合的设计原则:
1、单一职责原则(Single Responsibility Principle)
适配器模式将转换接口的职责单独封装在适配器中。
2、开闭原则(Open Closed Principle)
可以通过继承适配器类来扩展系统,而不需要修改原有代码。
3、接口隔离原则(Interface Segregation Principle)
适配器模式使得接口中的方法更加聚合和职责单一。
4、依赖倒转原则(Dependency Inversion Principle)
目标依赖适配器接口,适配器依赖于适配者接口,降低了依赖性。
5、组合复用原则(Composite Reuse Principle)
存在组合关系而不是继承关系,增强了适配器的扩展性。
适配器模式通过转换接口使原本不兼容的类可以合作无间,提高了类的复用性。它还可以帮助接口升级优化而不破坏客户端。