适配器模式(Adapter Pattern):接口转换的桥梁
适配器模式是结构型设计模式的一种,核心思想是将一个类的接口转换为客户端期望的另一个接口,使原本因接口不兼容而无法协同工作的类能够一起工作。它就像生活中的 “转换插头”,让不同规格的设备可以互通,核心功能是 “转换匹配,复用已有功能”。
适配器模式的核心结构

适配器模式
适配器模式包含三个核心角色,通过转换实现接口兼容:
目标角色(Target)
- 客户端期望的目标接口,定义了客户端需要的方法。
- 示例:
USB接口(客户端设备需要的接口)。
被适配角色(Adaptee)
- 已存在的旧接口,其功能需要被复用,但与目标接口不兼容。
- 示例:
Type-C接口(已有设备的接口,与 USB 不兼容)。
适配器角色(Adapter)
- 实现目标接口,并包装被适配对象,将目标接口的方法转换为被适配接口的方法调用。
- 示例:
USB-TypeC转换器(实现 USB 接口,内部调用 Type-C 设备的功能)。
适配器模式的两种实现方式
根据适配器与被适配对象的关系(继承 / 组合),适配器模式分为类适配器和对象适配器。
1. 类适配器(基于继承)
通过继承被适配类并实现目标接口,将被适配类的方法转换为目标接口的方法。
代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| interface Target { void request(); }
class Adaptee { public void specificRequest() { System.out.println("被适配类:执行特定功能"); } }
class ClassAdapter extends Adaptee implements Target { @Override public void request() { super.specificRequest(); } }
public class ClassAdapterDemo { public static void main(String[] args) { Target target = new ClassAdapter(); target.request(); } }
|
2. 对象适配器(基于组合)
通过组合被适配对象(持有 Adaptee 的引用)并实现目标接口,更灵活,是更常用的方式。
代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| interface Target { void request(); }
class Adaptee { public void specificRequest() { System.out.println("被适配类:执行特定功能"); } }
class ObjectAdapter implements Target { private Adaptee adaptee;
public ObjectAdapter(Adaptee adaptee) { this.adaptee = adaptee; }
@Override public void request() { adaptee.specificRequest(); } }
public class ObjectAdapterDemo { public static void main(String[] args) { Adaptee adaptee = new Adaptee(); Target target = new ObjectAdapter(adaptee); target.request(); } }
|
两种适配器的对比
| 方式 |
实现方式 |
优点 |
缺点 |
| 类适配器 |
继承 Adaptee + 实现 Target |
结构简单,直接调用父类方法 |
只能适配单一类,不支持多继承 |
| 对象适配器 |
组合 Adaptee + 实现 Target |
可适配多个类(多组合) |
需额外包装,代码略复杂 |
经典应用案例:Spring MVC 的 HandlerAdapter
Spring MVC 中,HandlerAdapter是适配器模式的典型应用,用于适配不同类型的处理器(Handler),使 DispatcherServlet 能统一调用处理器的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| public interface HandlerAdapter { boolean supports(Object handler); ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception; }
public interface Controller { ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception; }
public interface HttpRequestHandler { void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException; }
public class SimpleControllerHandlerAdapter implements HandlerAdapter { @Override public boolean supports(Object handler) { return handler instanceof Controller; } @Override public ModelAndView handle(...) { return ((Controller) handler).handleRequest(request, response); } }
public class HttpRequestHandlerAdapter implements HandlerAdapter { @Override public boolean supports(Object handler) { return handler instanceof HttpRequestHandler; } @Override public ModelAndView handle(...) { ((HttpRequestHandler) handler).handleRequest(request, response); return null; } }
|
工作原理:
DispatcherServlet 通过HandlerAdapter的handle()方法调用不同类型的处理器,无需关心处理器的具体接口(Controller/HttpRequestHandler),实现了请求处理的统一调度。
优缺点分析
优点
- 复用现有功能
无需修改已有类(Adaptee),通过适配器使其适配新接口,复用已有功能,符合开闭原则。
- 解耦客户端与被适配类
客户端仅依赖目标接口,与被适配类隔离,降低耦合度。
- 灵活性高
可通过更换适配器切换不同的被适配类,适应不同场景(如对象适配器可组合多个被适配类)。
缺点
- 增加系统复杂度
引入适配器会增加额外的类和层次,可能使代码结构更复杂(过多适配器会导致逻辑混乱)。
- 转换开销
适配器的转换逻辑可能引入轻微的性能损耗(通常可忽略)。
适用场景
- 接口不兼容的系统集成
当需要使用已有类(如第三方库、 legacy 系统),但其接口与当前系统不兼容时,用适配器转换。
- 复用老旧代码
对历史代码进行封装,使其适配新系统的接口,避免重写功能。
- 统一接口规范
当多个类实现相似功能但接口不同时,用适配器统一为一个接口(如 Spring MVC 的 HandlerAdapter)。
- 测试驱动开发
为测试模拟对象创建适配器,适配测试接口与实际接口。
总结
适配器模式是 “接口转换” 的利器,通过类继承或对象组合,使不兼容的接口能够协同工作。其核心价值在于复用现有功能和解耦接口依赖,尤其适合系统集成、老旧代码复用等场景。在实际开发中,对象适配器因灵活性更高而更常用,但需注意避免过度使用导致系统臃肿
v1.3.10