本文实例代码:https://github.com/JamesZBL/java_design_patterns
适配器(Adapter)模式用来将两个不同的接口进行适配,所以它是一种结构型的模式。适配器可以实现把一种接口进行转换,从而能够适应客户端的需求,所以它解决了两个类之间因为接口不匹配而无法工作的问题。适配器在日常生活中也很常见,比如 Micro-SD 卡需要一个转换器才在大多数的笔记本上存取数据,两脚插头需要转换器才能在只提供三脚插孔的插座上使用,Micro-USB 的数据线需要转换器才能在只具备 Type-C 的接口的设备之间传输数据等等…… 这些转换设备都属于适配器,它们都将一种接口转换成另一种接口,而使用者只需了解转换设备如何使用即可,无需关注其内部实现逻辑。
实例
老张有辆小汽车,他每天都开着它上下班,我们将小汽车抽象成 Car
接口:
Car.java1
2
3
4public interface Car {
void drive();
}
老张驾驶小汽车很熟练,所以老张(司机)实现了 Car
接口
Driver.java
1 | public class Driver implements Car { |
某个周末,他的小汽车被朋友借走了,但是公司突发紧急情况需要他马上赶到公司。打了一圈电话之后发现,只有一个开大巴的朋友的车当天没有任务,思考了片刻后,老张还是把大巴车借过来了(有点扯了,不过当初代码写成这样的时候并不觉得扯,所以继续扯下去吧)。他之所以能把大巴车借来,是因为他自己是有大车的驾驶证的,他又犹豫了片刻是因为他已经多年没有驾驶过大车了。
驾驶小汽车的方式和大巴车是有一定差别的,这只大巴车的接口 Bus
:
Bus.java
1 | public class Bus { |
老张上车后发现对车上的各种设备都不熟悉,于是向车主朋友请教,经过朋友几分钟的讲解,老张经过和小汽车的类比,将自己驾驶大车的技能又“激活”了,这时的老张就可以被视为一种适配器,我们将他抽象为 BusAdapter
BusAdapter.java
1 | public class BusAdapter implements Car { |
有了这个“适配器”,大巴车成功的被开到了公司:
1 | public class Application { |
总结
适配器模式的使用场景有:
- 需要使用的类的接口与需要的接口类型不匹配
- 需要创建一个可重用的类,它可以与不相关的或不可预见的类进行协作,也就是说,类不一定具有兼容的接口
- 需要使用几个现有的子类,但是通过子类化每个子类来调整它们的接口是不切实际的。对象适配器可以调整其父类的接口
适配器又可以分为对象适配器和类适配器,上面的实例就是类适配器的一种,类适配器和对象适配器的却别有:
- 类适配器的适配功能是通过被适配类(接口)的一个对象间接完成的。因此,类适配器不能无法
对被适配类的所有子类进行适配 - 类适配器重写了被适配类(接口)的方法,所以,类适配器可以看做被适配类(接口)的一个子类,上面例子中的
BusAdapter
类就可以视为Car
的一个子类 - 类适配器一般只需持有一个被适配类(接口)的对象,并不需要额外的对被适配类(接口)的引用,
BusAdapter
只对Car
接口进行了适配 - 对象适配器可以和多个被适配类(接口)的对象协同工作——即被适配类(接口)本身及其所有子类。适配器也可以一次为所有的被适配类(接口)添加自定义的功能
- 对象适配器使得重写被适配类(接口)的方法变成了不可能,这时需要的是被适配类(接口)的子类,而不是被适配类(接口)本身
适配器模式的主要目的是解决接口之间不匹配的问题,所以它经常被用来解决现有设计中结构设计问题,使得软件在不修改既有类或接口的情况下实现新的功能组合。