19.2 适配器模式的定义

19.2 适配器模式的定义

适配器模式(Adapter Pattern)的定义如下:

Convert the interface of a class into another interface clients expect.Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces.(将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。)

适配器模式又叫做变压器模式,也叫做包装模式(Wrapper),但是包装模式可不止一个,还包括了第17章讲解的装饰模式。适配器模式的通用类图,如图19-4所示。

image-20210929162035428

图19-4 适配器模式通用类图
适配器模式在生活中还是很常见的,比如你笔记本上的电源适配器,可以使用在110~ 220V之间变化的电源,而笔记本还能正常工作,这也是适配器一个良好模式的体现,简单地说,适配器模式就是把一个接口或类转换成其他的接口或类,从另一方面来说,适配器模式也就是一个包装模式,为什么呢?它把Adaptee包装成一个Target接口的类,加了一层衣服, 包装成另外一个靓妞了。大家知道,设计模式原是为建筑设计而服务的,软件设计模式只是借用了人家的原理而已,那我们来看看最原始的适配器是如何设计的,如图19-5所示。

A、B两个图框代表已经塑模成型的物体A和物体B,那现在要求把A和B安装在一起使用,如何安装?两者的接口不一致,是不可能安装在一起使用的,那怎么办?引入一个物体C,如图19-6所示。

image-20210929162142279

图19-5 两个已经成型的物体

引入物体C后,C适应了物体A的接口,同时也适应了物体B的接口,然后三者就可以组合成一个完整的物体,如图19-7所示。

image-20210929162925512

图19-7 完美组合

其中的物体C就是我们说的适配器,它在中间起到了角色转换的作用,把原有的长条形接口转换了三角形接口。在我们软件业的设计模式中,适配器模式也是相似的功能,那我们先来看看适配器模式的三个角色。

  • Target目标角色

该角色定义把其他类转换为何种接口,也就是我们的期望接口,例子中的IUserInfo接口就是目标角色。

  • Adaptee源角色

你想把谁转换成目标角色,这个“谁”就是源角色,它是已经存在的、运行良好的类或对象,经过适配器角色的包装,它会成为一个崭新、靓丽的角色。

  • Adapter适配器角色

适配器模式的核心角色,其他两个角色都是已经存在的角色,而适配器角色是需要新建立的,它的职责非常简单:把源角色转换为目标角色,怎么转换?通过继承或是类关联的方式。

各个角色的职责都已经非常清楚,我们再来看看其通用源码,目标接口如代码清单19-8 所示。

代码清单19-8 目标角色

1
2
3
4
public interface Target {
//目标角色有自己的方法
public void request();
}

目标角色是一个已经在正式运行的角色,你不可能去修改角色中的方法,你能做的就是如何去实现接口中的方法,而且通常情况下,目标角色是一个接口或者是抽象类,一般不会是实现类。一个正在服役的目标角色,如代码清单19-9所示。

代码清单19-9 目标角色的实现类

1
2
3
4
5
public class ConcreteTarget implements Target {
public void request() {
System.out.println("if you need any help,pls call me!");
}
}

源角色也是已经在服役状态(当然,非要新建立一个源角色,然后套用适配器模式,那也没有任何问题),它是一个正常的类,其源代码如代码清单19-10所示。

代码清单19-10 源角色

1
2
3
4
5
6
public class Adaptee {
//原有的业务逻辑
public void doSomething(){
System.out.println("I'm kind of busy,leave me alone,pls!");
}
}

我们的核心角色要出场了,适配器角色如代码清单19-11所示。

代码清单19-11 适配器角色

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

所有的角色都已经在场了,那我们就开始看看这场演出,场景类如代码清单19-12所示。

代码清单19-12 场景类

1
2
3
4
5
6
7
8
9
10
public class Client {
public static void main(String[] args) {
//原有的业务逻辑
Target target = new ConcreteTarget();
target.request();
//现在增加了适配器角色后的业务逻辑
Target target2 = new Adapter();
target2.request();
}
}

适配器模式的原理就讲这么多吧,但是别得意得太早了,如果你认为适配器模式就这么简单,那我告诉你,你错了!复杂的还在后面。