设计模式——适配器模式(类适配器、对象适配器)
是什么?
我们平时的有线耳机接口分为USB的和Type-C的接口,但是手机的耳机插口却只有一个,像华为的耳机插口现在基本都是Type-c的,那如果我们现在只有USB接口的耳机怎么办呢,这个时候就需要使用到一个转换器,这个转换器是USB接口的,插入USB插口中,然后它的背面可供Type-C的接口插入,最终实现一个转换效果,这其实就是使用到了适配器模式;
因此适配器模式就是将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作;
适配器模式分为类适配器模式和对象适配器模式,前者类之间的耦合度比后者高,且要求程序员了解现有组件库中的相关组件的内部结构,所以应用相对较少些;
结构
目标接口:当前系统业务所期待的接口,它可以是抽象类或接口;
适配者类:它是被访问和适配的现存组件库中的组件接口;
适配器类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者;
实现
类适配器
实现方式:定义一个适配器类来实现当前系统的业务接口,同时又继承现有组件库中已经存在的组件;
目标接口
public interface USB {
//目标接口
void connectByUsb();
}
public class IUSBImpl implements USB{
@Override
public void connectByUsb() {
System.out.println("连接USB接口");
}
}
适配者类
//适配器
public class Adapter extends ITypeCImpl implements USB{
@Override
public void connectByUsb() {
System.out.println("使用适配器");
connectByTypeC();
}
}
适配器类
//适配器
public class Adapter extends ITypeCImpl implements USB{
@Override
public void connectByUsb() {
System.out.println("使用适配器");
connectByTypeC();
}
}
使用
public class Phone {
public void connectHeadset(USB usb){
usb.connectByUsb();
}
}
public class Consumer {
public static void main(String[] args) {
Phone phone = new Phone();
Adapter adapter = new Adapter();
IUSBImpl usb = new IUSBImpl();
phone.connectHeadset(usb);
System.out.println("==========================");
phone.connectHeadset(adapter);
}
}
我们可以这样理解:我们原来使用USB接口直接连接手机的USB接口,而现在我们手里的耳机是TypeC接口,因此是不能直接连接手机接口的,我们只能连接转换器(适配器),然后让转换器帮我们转换然后去连接手机的USB接口;
缺点
类适配器模式违背了合成复用原则,类适配器是客户类有一个接口规范的情况下可用,反之则不可用;也就是说如果我们的适配器是实现了USB接口规范的,但如果它本身没有这个接口规范,而只有单单一个类的情况下就没办法使用了(继承只能单继承)
对象适配器
实现方式:对象适配器模式可采用将现有组件库中已经实现的组件引入适配器类中,该类同时实现当前系统的业务接口;
目标接口
public interface USB {
//目标接口或目标对象
void connectByUsb();
}
public class IUSBImpl implements USB {
@Override
public void connectByUsb() {
System.out.println("连接USB接口");
}
}
适配者类
public interface TypeC {
//适配者
void connectByTypeC ();
}
public class ITypeCImpl implements TypeC {
@Override
public void connectByTypeC() {
System.out.println("使用Type-C接口连接");
}
}
适配器类
//适配器
public class Adapter extends IUSBImpl {
//聚合适配者类
private TypeC typeC;
public Adapter(TypeC typeC) {
this.typeC = typeC;
}
@Override
public void connectByUsb() {
System.out.println("适配器连接USB接口");
typeC.connectByTypeC();
}
}
使用
public class Phone {
public void connectHeadset(USB usb){
usb.connectByUsb();
}
}
public class Consumer {
public static void main(String[] args) {
Phone phone = new Phone();
IUSBImpl usb = new IUSBImpl();
//直接使用USB连接
phone.connectHeadset(usb);
System.out.println("==========================");
ITypeCImpl typeC = new ITypeCImpl();
Adapter adapter = new Adapter(typeC);
//通过适配器连接
phone.connectHeadset(adapter);
}
}
简单来说,我们在适配器中没有直接去继承适配者的实现类,而是聚合了适配者类,这样的话无论我们的目标对象不管是类还是接口都可以完美实现了,且符合合成复用原则;
注意:还有一个适配器模式是接口适配器模式,当不希望实现一个接口中所有方法的时候,可以创建一个抽象类Adapter,实现所有方法,而此时我们只需要继承该抽象类即可,比较简单就不再过多赘述;
使用场景
1.以前开发的系统存在满足新系统功能需求的类,但其接口同新系统的接口不一致;
2.使用第三方提供的组件,但组件接口定义和自己要求的接口定义不同;