设计模式五:适配器
适配器模式:将一个类的接口,转换为客户期望的另一个接口。适配器让原本接口不兼容的类合作无间。是一种结构型设计模式。
先来看一个示例:我有一个手机充电器,但接口是Micro-USB,但我的手机需要使用Type-C。在不换充电器的情况下,我可通过一个装接头,把Micro-USB转成Type-C。
java 代码
代码: micro-usb接口:
public interface IMicroUSB {
void powerWithMicroUSB();
}
micro-usb实现:
public class MicroUSBImpl implements IMicroUSB {
@Override
public void powerWithMicroUSB() {
System.out.println("使用Micro-USB给手机充电");
}
}
type-c接口:
public interface ITypeC {
void powerWithTypeC();
}
type-c实现:
public class TypeCImpl implements ITypeC {
@Override
public void powerWithTypeC() {
System.out.println("使用type-c给手机充电");
}
}
微usb充电器:
public class Charger {
private IMicroUSB microUSB;
public Charger(IMicroUSB microUSB) {
this.microUSB = microUSB;
}
public void setMicroUSB(IMicroUSB microUSB) {
this.microUSB = microUSB;
}
public void chage(){
microUSB.powerWithMicroUSB();
}
}
测试:
public class Test {
public static void main(String[] args) {
IMicroUSB microUSB = new MicroUSBImpl();
Charger charger = new Charger(microUSB);
charger.chage();
}
}
使用Micro-USB给手机充电
从运行结果看到,不是我们想要的结果。我们需要一个转接头(适配器):
public class ChargePortAdapter implements IMicroUSB{
private ITypeC typeC;
public ChargePortAdapter(ITypeC typeC) {
this.typeC = typeC;
}
@Override
public void powerWithMicroUSB() {
typeC.powerWithTypeC();
}
}
再测试
public class Test {
public static void main(String[] args) {
ITypeC typeC = new TypeCImpl();
ChargePortAdapter chargePortAdapter = new ChargePortAdapter(typeC);
Charger charger = new Charger();
charger.setMicroUSB(chargePortAdapter);
charger.chage();
}
}
使用type c给手机充电
得到了我们想要的结果。
类图和角色
上列类图:
- Target: 目标抽象类(IMicroUSB),定义客户所需接口,可以是一个抽象类或接口,也可以是具体类
- Adapter: 适配类(ChargeProtAdapter)。作为一个转换器,对Adaptee和Target进行适配,适配器类是适配器模式的核心。两个关键点:实现target;持有被适配接口的引用。
- Adaptee:适配者类(ITypeC),适配者即被适配的角色,它定义了一个已经存在的接口,这个接口需要适配。
适配器有对象适配器和类适配器。
优缺点
优点:
- 将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,而无须修改原有代码。
- 一个对象适配器可以把多个不同的适配者适配到同一个目标,也就是说,同一个适配器可以把适配者类和它的子类都适配到目标接口。
缺点:
- 类适配器:Java不支持多重继承的语言,一次最多只能适配一个适配者类,而且目标抽象类只能为抽象类,不能为具体类,其使用有一定的局限性,不能将一个适配者类和它的子类都适配到目标接口。
- 对象适配器:类适配器模式相比,要想置换适配者类的方法就不容易。如果一定要置换掉适配者类的一个或多个方法,就只好先做一个适配者类的子类,将适配者类的方法置换掉,然后再把适配者类的子类当做真正的适配者进行适配,实现过程较为复杂。