适配器模式详解
适配器模式(Adapter Pattern)是解决项目新老版本接口兼容问题的常用手段。当新系统需要调用旧系统的接口,但两者定义不一致时,通过一个适配器作为中间件进行转换,使得原本无法直接调用的老版本接口能够在新环境中复用,同时不影响老版本已有的既定实现。这不仅提高了代码的可复用性,也增强了系统的可扩展性。
核心角色与原理
在适配器模式中,主要涉及三个角色:
- 源(Adaptee):需要被适配的对象或类型,通常是旧版本接口或特定功能的实现,一般不能随意改动。
- 适配器(Adapter):连接目标和源的中间对象,相当于插头转换器,负责将源角色的功能转换为目标角色期望的格式。
- 目标(Target):期待得到的目标接口,通常是新版本的标准接口,支持动态扩展。
这种模式满足开闭原则:对扩展开放,对修改关闭。具体到适配器模式中,意味着我们可以动态扩展目标角色,而无需改动源角色。
源角色和目标角色的关联关系通常是一对多的(源 : 目标 = 1:N)。根据实现方式的不同,适配器模式主要分为三种形式:
- 类适配器模式:适配器类继承源类,并实现目标接口。
- 对象适配器模式:适配器类实现目标接口,内部持有源类的实例(组合方式)。
- 接口适配器模式:当不需要重写接口中的所有方法时,提供一个抽象类作为过渡,默认提供空方法实现,子类只需重写需要的方法。
典型应用场景
适配器模式的应用非常广泛,特别是在以下场景:
- 项目新老版本迭代:保留老版本既定功能,同时动态扩展新功能,减少老版本代码改动量。
- 第三方框架集成:例如 MyBatis 框架支持多种日志系统(Log4J、SLF4J 等),内部使用统一的日志接口来兼容不同类型的日志框架。
优缺点分析
优点: 系统可以使用现有的类,即使其接口不符合当前需求。通过适配器模式,可以让这些功能得到更好的复用,自然地扩展系统功能。
缺点: 过多的使用适配器会让系统变得零乱,不易整体把握。比如明明调用的是 A 接口,实际内部被适配成了 B 接口的实现。如果系统中出现大量此类情况,无异于一场灾难。因此,如果不是很有必要,建议直接对系统进行重构。
代码实战:订单接口适配
假设早期 V1 版本的订单接口入参为 Map 类型,随着业务更新,V2 版本需要支持 List 类型。在不改变原有接口代码的情况下,如何实现?
首先看原有的 Map 处理逻辑:
public void froOrderMap(Map map) {
for (int i = 0; i < map.size(); i++) {
// 使用索引作为 MapKey 获取数据
String value = (String) map.get(i);
System.out.println("value:" + value);
}
}
我们需要创建一个适配器,让 List 看起来像 Map 一样被访问。这里采用类适配器思路,继承 HashMap 并重写关键方法:
{
List list;
{
.list = list;
}
{
list.size();
}
Object {
list.get(Integer.valueOf(key.toString()).intValue());
}
}

