适配器模式

适配器模式–不兼容结构的协调

将一个接口转换成客户希望的另一个接口,使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。

根据适配器类与适配者类的关系不同,适配器模式可分为对象适配器和类适配器两种:
在对象适配器模式中,适配器与适配者之间是关联关系;在类适配器模式中,适配器与适配者之间是继承(或实现)关系

对象适配器:

在对象适配器模式结构中有以下几个角色:
● Target(目标抽象类):目标抽象类定义客户所需接口,可以是一个抽象类或接口,也可以是具体类。

● Adapter(适配器类):适配器可以调用另一个接口,作为一个转换器,对Adaptee和Target进行适配,适配器类是适配器模式的核心。在对象适配器中,它通过继承Target并关联一个Adaptee对象使二者产生联系。

● Adaptee(适配者类):适配者即被适配的角色,它定义了一个已经存在的接口,这个接口需要适配,适配者类一般是一个具体类,包含了客户希望使用的业务方法,在某些情况下可能没有适配者类的源代码。

1
2
3
4
5
6
7
8
9
10
11
class Adapter extends Target { //继承目标抽象类Target,并重写其request方法
private Adaptee adaptee; //维持一个对适配者对象的引用
public Adapter(Adaptee adaptee) {
this.adaptee=adaptee; //在适配器中实例化适配者对象
}
public void request() {
adaptee.specificRequest(); //转发调用,即实现request()接口和specialRequest()接口的适配。
}
}

注:client希望希望调用request()接口来实现其所需的业务逻辑,Adaptee类的specialRequest()接口刚好可以完成其业务逻辑(其源代码是无法获取的),此时需要上面的这种适配。上面的Adapter和Adaptee是一种关联关系(委派关系)。

类适配器:

类适配器模式和对象适配器模式最大的区别在于适配器和适配者之间的关系不同,对象适配器模式中适配器和适配者之间是关联关系,而类是配器模式中适配器和适配者是继承关系。
典型的类适配器代码如下所示:

1
2
3
4
5
class Adapter extends Adaptee implements Target {
public void request() {
specificRequest();
}
}

适配器类实现了抽象目标类接口Target,并继承了适配者类,在适配器类的request()方法中调用所继承的适配者类的specificRequest()方法,实现了适配。
由于Java、C#等语言不支持多重类继承,因此类适配器的使用受到很多限制,例如如果目标抽象类Target不是接口,而是一个类,就无法使用类适配器;此外,如果适配者Adapter为最终(Final)类,也无法使用类适配器。在Java等面向对象编程语言中,大部分情况下我们使用的是对象适配器,类适配器较少使用。

适配器模式的总结:
适配器模式将现有接口转化为客户类所希望的接口,实现了对现有类的复用。在软件开发中得以广泛应用,在Spring等开源框架驱动程序设计中也使用了适配器模式。

适用场景
在以下情况下可以考虑使用适配器模式:
(1) 系统需要使用一些现有的类,而这些类的接口(如方法名)不符合系统的需要,甚至没有这些类的源代码。
(2) 想创建一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。