一、介绍
适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。
这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。
举个例子,现在市面上很多手机都是typeC的接口,但我们的U盘都是usb格式的接口,因此这两个接口是不兼容的,如果我们能在手机上使用usb的U盘,那将会方便很多。因此我们需要一个适配器,适配器的输入端插入U盘,输出端以TypeC的格式插到手机上,这样,手机就可以读取U盘中的文件了。
下面我们使用两种方式来解决这种接口不兼容的问题
- 不使用设计模式
- 使用适配器设计模式
二、代码示例
我们以手机和u盘为例,使用两种分别有USB接口和TypeC接口的手机,和两个分别为USB接口和TypeC接口的U盘,下面来看这两个手机如何使用这两个U盘。
1. 新建两种类型的U盘
usb类型的U盘
public interface USB { public void work(); } @Slf4j public class USBDisk implements USB { public USBDisk() { log.info("我是usb格式的U盘"); } public void work() { log.info("usb格式的u盘正在提供数据服务"); } }
typeC类型的U盘
public interface TypeC { public void work(); } @Slf4j public class TypeCDisk implements TypeC { public TypeCDisk() { log.info("我是typeC格式的U盘"); } public void work() { log.info("typeC格式的u盘正在提供数据服务"); } }
2. 新建两种不同类型手机及其对应的实现类
usb插槽的手机
public interface USBPhone { public void work(USB usb); } @Slf4j public class USBVivo implements USBPhone { public USBVivo() { log.info("我是vivo手机,我只提供usb插槽"); } @Override public void work(USB usb) { usb.work(); } }
typeC插槽的手机
public interface TypeCPhone { public void work(TypeC typeC); } @Slf4j public class TypeCHuaWei implements TypeCPhone { public TypeCHuaWei() { log.info("我是华为手机,我只提供typeC插槽"); } public void work(TypeC typeC) { typeC.work(); } }
3. 运行示例
在手机和U盘相互兼容的情况下,我们可以很简单的就把代码完成。
提供usb插槽的vivo手机使用usb类型的U盘
public class USBPhoneDemo { public static void main(String[] args) { // usb类型的U盘 USBDisk disk = new USBDisk(); // usb插槽的vivo手机 USBPhone vivo = new USBVivo(); // vivo从U盘读取数据 vivo.work(disk); } }
输出
提供typeC插槽的华为手机使用typeC类型的U盘
public class TypeCPhoneDemo { public static void main(String[] args) { // typeC类型的U盘 TypeC disk = new TypeCDisk(); // usb插槽的华为手机 TypeCPhone huaWei = new TypeCHuaWei(); // 华为从U盘读取数据 huaWei.work(disk); } }
输出
但是在手机插槽和U盘不兼容的情况下,手机是无法通过U盘读取数据的,这时我们需要适配器。
4. 新建适配器类
新建将usb转为typeC的适配器类
USB2TypeCAdapter
因为该适配器输入USB类型的U盘,输出的是typeC的接口,所以本质上是一个TypeC类型的设备
@Slf4j public class USB2TypeCAdapter implements TypeC { private final USB disk; public USB2TypeCAdapter(USB disk) { log.info("适配器正在适配usb类型的U盘与typeC插槽的手机..."); this.disk = disk; } // 适配器工作时,其实是适配器内的usb在工作 @Override public void work() { disk.work(); } }
适配器的应用
typeC插槽的手机通过适配器读取usb类型的U盘
public class Usb2TypeCDemo { public static void main(String[] args) { // usb形式的U盘 USB usb = new USBDisk(); // 输出:我是usb格式的U盘 // 但我的手机是typeC手机华为,因此我只能接收typeC类型的U盘 TypeCPhone huawei = new TypeCHuaWei(); // 输出:我是华为手机,我只提供typeC插槽 // 这时我搞一个usb适配器,这个适配器供typeC手机使用,适配器一头连接huawei, 一头连接U盘 USB2TypeCAdapter usbUSB2TypeCAdapter = new USB2TypeCAdapter(usb); // 输出:适配器正在适配usb与typeC... // 华为从适配器中读取数据 huawei.work(usbUSB2TypeCAdapter); // 输出:usb接口的u盘正在提供数据服务 } }
输出
新建将typeC转为usb的适配器类
TypeC2USBAdapter
因为该适配器输入typeC类型的U盘,输出的是usb的接口,所以本质上是一个usb类型的设备
public class TypeC2USBAdapter implements USB { private final TypeC disk; public TypeC2USBAdapter(TypeC disk) { log.info("适配器正在适配usb类型的U盘与typeC插槽的手机..."); this.disk = disk; } @Override public void work() { disk.work(); } }
适配器的应用
usb插槽的手机通过适配器读取typeC类型的U盘
public class TypeC2USBDemo { public static void main(String[] args) { // typeC形式的U盘 TypeC typeC = new TypeCDisk(); // 输出:我是typeC格式的U盘 // 但我的手机是usb手机vivo,因此我只能接收usb类型的U盘 USBPhone vivo = new USBVivo(); // 输出:我是vivo手机,我只提供usb插槽 // 这时我搞一个usb适配器,这个适配器供typeC手机使用,适配器一头连接huawei, 一头连接U盘 TypeC2USBAdapter typeC2USBAdapter = new TypeC2USBAdapter(typeC); // 输出:适配器正在适配typeC类型的U盘与usb插槽的手机... // vivo从适配器中读取数据 vivo.work(typeC2USBAdapter); // 输出:typeC格式的u盘正在提供数据服务 } }
输出
三、总结
适配器模式本质上就是一个适配器类作为两个不兼容类的桥梁。
纸上得来终觉浅,绝知此事要躬行。
————————我是万万岁,我们下期再见————————