一、定义
将一个的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
二、背景
有时,为复用而设计的工具类不能被复用的原因恰恰是因为它的接口和专业领域现有的接口不匹配。如果遇到了接口无法兼容的问题,我们可以改掉工具类的接口使之适应于现有的接口,但前提是你拥有修改工具类的权限;即使你拥有的修改工具类源代码的权限,我们仅仅为了一个应用就让工具类不得不采用一些与特定领域相关的接口,这样是否合适呢?
这个时候,我们可以不调整工具,只需要定义一个适配器类,这个适配器类引用工具类并实现特定领域接口,在这个适配器类中通过委托的方式实现功能。两全其美。
例如,有一个图形编辑器,这个编辑器允许用户创建基本图形。我们创建Shap作为接口,并实现了创建圆形的类Circle和正方形的类Square;现在新的需求来了,编译器还允许用户绘制复杂图形,因为绘图功能复杂,而我们刚好有现成的工具类Drawing可以用,那么我们可以做做一个适配器DrawingShape,这个适配器实现Shape接口并且将绘图的功能转交给Drawing。我们将DrawingShape称为适配器Adapter。
三、适用性
1.想使用一个现有的类,而它的接口不符合你的需求;
2.你想创建一个可复用的类,该类可以与其他不相关的类或不可预见的类(有可能是接口不兼容的)协同工作;
3.你想使用一些已经存在的子类,但不可能对每个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口。这个场景仅适用于对象版本的适配器模式。
四、UML类图
Adapter模式可以有两种版本:类版本的和对象版本
1.类版本。类适配器使用多种继承的方式对一个接口和另一个类做继承。在Java语言中,如果想多继承,必须把Target设计成接口。
2.对象版本。在Adapter中声明一个指向Adaptee对象的引用。
五、类职责
1.Target:
1)定义Client使用的与特定领域相关的一些接口
2.Client:
1)与符合Target接口的对象交互
3.Adaptee
1)一个已经存在的接口,是需要适配的接口
4.Adapter
1)对Adaptee接口和Target接口进行适配
六、协作
Client在Adapter的实例上调用一些操作,Adapter将调用请求委托给Adaptee。
七、效果
类适配器和对象适配器有不同的权衡。类适配器
1)用一个具体的Adapter对Adaptee和Target进行匹配。结果是当我们想要匹配一个类以及它的子类时,类Adapter不能胜任;
2)使Adapter可以重定义Adaptee的部分行为,因为Adapter是Adaptee的一个子类;
3)仅仅引入了一个对象,并不需要在Adapter中添加一个字段指向Adaptee的引用;
而对象适配器则
1)允许一个Adapter与多个Adaptee一起工作,Adapter也可以一次给所有Adaptee添加功能;
2)使得重定义Adaptee的行为比较困难。这就需要生成Adaptee的子类并且让Adapter引用这个子类而不是Adaptee。
八、注意事项
在使用适配器模式时,还需要考虑Adaptee和Target的匹配度,如果匹配度比较高,则Adapter的代码量就比较少,如果匹配度比较低,就需要比较多的代码量来协作。
适配器模式不是为了解决还处于开发阶段的问题,而是解决已经存在的系统问题,如果在系统开始阶段就引入适配器模式,就需要考虑设计是不是出了问题。