将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
场景分析
比如我们的手机接口,小米6手机只有 type c 接口,同时用于听歌与充电。标准手机接口分别有 3.5mm 耳机接口跟 type c 充电接口。假如现在我们只有 3.5mm 的耳机要在小米6手机上听歌,那个就需要一个适配器 将我们的3.5mm 耳机适配到目标接口 小米6 的 type c,从而实现听歌。
适配器模式在生活中还是很常见的,比如你笔记本上的电源适配器,可以使用在110~220V之间变化的电源,而笔记本还能正常工作,这也是适配器一个良好模式的体现,简单地说,适配器模式就是把一个接口或类转换成其他的接口或类,从另一方面来说,适配器模式也就是一个包装模式,为什么呢?它把Adaptee包装成一个Target接口的类,加了一层衣服,包装成另外一个靓妞了。装饰器模式详情请看历史文章。
UML类图
- target 目标角色:该角色定义把其他类转换为何种接口,也就是我们的期望接口,例子中就是我们的小米6 type c 接口。
- Adapter适配器角色:适配器模式的核心角色,其他两个角色都是已经存在的角色,而适配器角色是需要新建立的,它的职责非常简单:把源角色转换为目标角色,怎么转换?通过继承或是持有类引用关联的方式。在例子中就是我们的 type c 接口转换器。
- Adaptee源角色:你想把谁转换成目标角色,这个“谁”就是源角色,它是已经存在的、运行良好的类或对象,经过适配器角色的包装,它会成为一个崭新、靓丽的角色。在例子中就是我们的 3.5mm 接口的耳机接口。
代码实战
- 首先我们先定义好 target 目标角色。也就是我们的小米6 type c 接口。以及手机默认的实现。
/** * Project: com-zero-design-stu * File created at 2019/6/24 19:45 */ package com.zero.headfirst.adapter.objects; /** * 通过小米6手机的 type-c 接口听歌,也可以充电(Target 角色) * @date 2019/6/24 19:45 */ public interface XiaoMi6Interface { /** * 听歌 */ void listenMusic(); }
以及小米6 type c 默认功能实现
/** * Project: com-zero-design-stu * File created at 2019/6/24 20:02 */ package com.zero.headfirst.adapter.objects; /** * 小米六 type c 接口默认实现功能 * @date 2019/6/24 20:02 */ public class XiaoMi6InterfaceImpl implements XiaoMi6Interface { @Override public void listenMusic() { System.out.println("通过 type c 接口的耳机听歌"); } }
- 定义我们的 Adaptee 角色,也就是我们的 3.5mm 接口的耳机。
package com.zero.headfirst.adapter.objects; /** * 普通手机通用 接口 ,对应的3.5mm 耳机孔 * @date 2019/6/25 16:28 */ public interface CommonPhoneInterface { /** * 听歌 */ void listenMusic(); } public class CommonPhoneImpl implements CommonPhoneInterface { @Override public void listenMusic() { System.out.println("标准手机 3.5 mm 耳机接口听歌"); } }
- 接着我们定义接口转换器,也就是适配器角色 Adapter。这里我们使用对象适配器方式,也就是适配器持有被适配的引用。同时实现 target 接口。
public class TypeC2HeadphoneAdapter implements XiaoMi6Interface { private CommonPhoneInterface commonPhoneInterface; public TypeC2HeadphoneAdapter(CommonPhoneInterface commonPhoneInterface) { this.commonPhoneInterface = commonPhoneInterface; } @Override public void listenMusic() { System.out.println("通过 type c 转 3.5mm适配器将目标 type c 接口适配上3.5mm接口。"); commonPhoneInterface.listenMusic(); } }
- 测试
public class Client { public static void main(String[] args) { //被适配者 3.5毫米耳机 CommonPhoneInterface headPhone = new CommonPhoneImpl(); //适配器 TypeC2HeadphoneAdapter typeC2HeadphoneAdapter = new TypeC2HeadphoneAdapter(headPhone); //通过适配器实现了听歌 typeC2HeadphoneAdapter.listenMusic(); } }
打印结果
通过 type c 转 3.5mm适配器将目标 type c 接口适配上3.5mm接口。 标准手机 3.5 mm 耳机接口听歌
总结
当我们的target 角色接口不能修改的情况下,我们的接口要转换适配使用就可以使用适配器模式。
装饰器模式侧重的是同一个接口增强新的功能并且复用。