来源:mikechen的互联网架构
设计模式是写出优秀程序的保障,与架构能力与阅读源码的能力息息相关,对程序员来说非常重要,非常值得深入学习。
前面,我们介绍了:
7 大设计原则(41张图解、2万多字)
5 大创建型设计模式总结,20 张图彻底掌握
适配器模式是结构型设计模式,它的作用是连接现有程序和所需程序。
当现有功能组件与当前系统的接口规范不兼容,无法直接使用时,重新开发的成本又很高,需要转换后才能使用,适配器模式很好地解决了这个问题。
这个描述有点抽象,列举一个日常生活中的常见例子。
例如:
苹果手机和华为手机的充电接口是不兼容的,如果要用华为的充电器给苹果手机充电,这时就需要转换接头进行适配。
随意找了一张图,这里只是为了说明这个道理。
适配器模式分为两种:对象适配器模式、类适配器模式。
国际惯例,先上手撕的 UML 类图。
1)对象适配器模式
对象适配器的 UML 类图:
对象的适配器模式的优点是灵活性高、低耦合。
其缺点是使用复杂,需要引入对象实例。
2)类适配器模式
类适配器模式的 UML 类图:
应用相对少,因为耦合度较高,且要求我们了解现有组件库中的相关组件的内部结构。
类适配器模式的优点是使用方便,代码简化,仅仅引入一个对象,并不需要额外的字段来引用 Adaptee 实例。
其缺点是高耦合,灵活性低,使用对象继承的方式,是静态的定义方式。
3)适配器模式的构成
适配器模式的构成主要为 3 个部分:
Target:适配器的内容,例如客户端使用的目标接口;
Adaptee:被适配的内容,例如不兼容的接口;
Adapter:适配器,把
Adeptee
适配成Target
。
假设:
为了改进项目的 log 系统,我们需要开发一个三方开源日志库。
但这个三方开源日志库与项目中的接口不兼容,为了解决这个问题,下面用适配器模式来完成这个功能。
1) 确定目标接口
系统原来的日志接口:
public interface LogFactory { void debug(String tag,String message);}
2)三方开源日志库的接口及实现
下面是第三方开源日志库提供的日志功能,它的接口与公司系统目前使用的不兼容。
public interface Logger { void d(int priority, String message, Object ... obj);}//具体提供日志功能的实现类public class LoggerImp implements Logger { @Override public void d(int priority, String message, Object... obj) { System.out.println(String.format("logger:%s",message)); }}
3)构建适配器类
通过适配器类,将第三方开源日志库提供的接口转换为系统的目标接口。
public class LogAdapter implements LogFactory {
private Logger Logger;
public LogAdapter(Logger Logger) {
this.Logger = Logger;
}
@Override
public void debug(String tag, String message) {
Objects.requireNonNull(Logger);
Logger.d(1, message);
}
}
LogAdapter 实现了系统的目标接口,同时持有三方库 Logger 的引用。
4)客户端使用
通过适配器,客户端很轻松就可以切换到新的日志系统了。
public class AdapterClient { public void recordLog() { LogFactory logFactory = new LogAdapter(new LoggerImp()); logFactory.debug("Test", "使用logger打印log"); }}
当需要使用一个现存的类,但它提供的接口与系统的接口不兼容,并且还不能修改它时;
使用第三方提供的组件,但组件接口定义和自己要求的接口定义不同时。
适配器模式的优点:
客户端通过适配器,可以透明地调用目标接口;
复用了现存的类,不需要修改原有代码,就能重用现有的适配者类。
将目标类和适配者类解耦,解决了目标类和适配者类接口不一致的问题。
适配器模式的缺点:
需要统一多个类的接口;
新旧 API 的兼容,改造成本高;
过多使用适配器,会让系统代码变得凌乱,增加系统的复杂性。
通过本文,我们了解并掌握了适配器模式,包括适配器模式的概念、作用、结构、使用场景、优缺点及应用等。
只有我们了解了每一种设计模式,实际应用时才能够合理选型,避免因强行使用设计模式、让代码更加不好维护的情况出现。