结构型—适配器模式
1、意图:
将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
2、场景描述:
手机的Usb数据线可以被看做适配器,不同类型的手机通过不同的Usb数据线连接到电脑相同的usb接口上。几年前的非智能手机,数据线连接手机的一端由于手机品牌的不同使用了各式各样的接口,但是连接电脑的一端却采用了相同usb接口。针对特定品牌的数据线使得每种不同的手机都可以连接到电脑的usb接口上,使得手机接口可以与电脑的usb接口协同工作。
另外,C++中的栈(stack)、队列(queue)被称作容器适配器,它们本身都是基于线性表来实现的,但是对外提供了特定的操作接口,如stack的LIFO(last-in first-out)特性。
3、适配器模式类图:
对象适配器类图:
角色:
- Client:用户类,使用新接口Target来完成某些特定的需求。
- Target:新的接口类,开放特定接口request来完成某些特定操作,与Client协作。
- Adaptee:原有的类。
- Adapter:适配器类,将Adaptee中的接口封装成Target中的新接口,来满足新的需求。
协作:
- Client调用Adapter实例的操作,Adapter使用Adaptee来完成这些被调用的操作。
注:
- 类图中表示的是适配器模式两种类图中的对象适配器类图,另外一种类适配器通过多重继承两个类或实现两个接口来实现。
4、适用性:
- 使用一个原本存在的类来满足新的需求,但是原来的类与新的需求类接口不一致。
- 希望复用原有的类,但是某些方法在原有的类中不存在,通过Adapter类来修改原来类Adaptee中的接口,并且添加Adaptee中不存在的方法。
5、实例类图:
说明:
- UsbPort、PhonePort分别是电脑Usb端口、手机端口的类定义信息。
- Human的将手机连接到电脑的操作(linkPhoneToComputer)使用UsbDataLine来完成。
6、代码实例:
手机端口类,含有手机端口的信息,对应适配器模式中的Adaptee。
1 package com.crazysnail.adapter; 2 3 public class PhonePort { 4 public void getPhonePort(){ 5 System.out.println("我是一个手机接口"); 6 } 7 }
Usb端口类,满足将设备连接到电脑的新需求,对应适配器模式中的Target。
1 package com.crazysnail.adapter; 2 3 public class UsbPort { 4 public void getUsbPort(){ 5 System.out.println("我是一个usb接口"); 6 } 7 }
数据线类,一端连接到手机端口,开放数据线另一端的usb接口,对应适配器模式中的Adapter。
1 package com.crazysnail.adapter; 2 3 public class UsbDataLine extends UsbPort{ 4 private PhonePort phonePort; 5 6 public UsbDataLine() { 7 System.out.println("获取一条匹配特性型号手机的数据线"); 8 phonePort = new PhonePort(); 9 } 10 11 @Override 12 public void getUsbPort(){ 13 phonePort.getPhonePort(); 14 System.out.println("手机接口连接到数据线一端,开放数据线的usb接口一端"); 15 } 16 }
人类类,有连接手机到电脑的需求,使用数据线将手机连接到电脑,对应适配器模式中的Client。
1 package com.crazysnail.adapter; 2 3 public class Human { 4 public static void linkPhoneToComputer(UsbDataLine line){ 5 line.getUsbPort(); 6 System.out.println("将Usb接口连接到电脑"); 7 } 8 }
测试类,效果演示。
1 package com.crazysnail.adapter; 2 3 public class AdapterTest { 4 public static void main(String[] args){ 5 UsbDataLine newUsbDataLine = new UsbDataLine(); 6 7 Human.linkPhoneToComputer(newUsbDataLine); 8 } 9 }
效果图:
7、适配器模式的特点
- 实现了类的复用,利用了原有的Adaptee类,通过Adapter接口的包装或改造,满足了新需求。
- 当需要冲定义Adaptee类时,可能会影响到Adapter中的操作。
【积跬步,至千里。 _CrazySnail_】