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

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