Skip to content
基础

一句话答案

将一个类的接口转换为客户端期望的接口,使不兼容的类协作;Spring HandlerAdapter 适配不同类型 Controller。

核心要点

适配器模式将一个类的接口转换成客户期望的另一个接口,使原本接口不兼容的类可以一起工作。

两种实现方式:

方式实现特点
类适配器适配器继承被适配类 + 实现目标接口Java 单继承限制,不常用
对象适配器适配器持有被适配对象的引用 + 实现目标接口推荐,组合优于继承
java
// 目标接口
public interface Target {
    void request();
}

// 被适配的类(旧接口)
public class Adaptee {
    public void specificRequest() { /* 旧逻辑 */ }
}

// 对象适配器
public class Adapter implements Target {
    private Adaptee adaptee;
    
    public Adapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }
    
    @Override
    public void request() {
        adaptee.specificRequest(); // 转发调用
    }
}

Spring MVC 中的 HandlerAdapter:

Spring MVC 支持多种类型的 Controller:

  • @Controller + @RequestMapping(注解式)
  • 实现 Controller 接口
  • 实现 HttpRequestHandler 接口

这些 Handler 的调用方式各不相同。HandlerAdapter 作为适配器,将不同类型 Handler 的调用方式统一:

DispatcherServlet

   ▼ 调用统一接口 adapter.handle(request, response, handler)
HandlerAdapter(目标接口)
   ├── RequestMappingHandlerAdapter  → 处理 @RequestMapping 注解的方法
   ├── SimpleControllerHandlerAdapter → 处理实现 Controller 接口的类
   └── HttpRequestHandlerAdapter     → 处理实现 HttpRequestHandler 的类

核心流程:

  1. DispatcherServlet 根据请求找到 Handler(Controller 方法)
  2. 遍历所有 HandlerAdapter,找到能处理该 Handler 的适配器(supports(handler) 返回 true)
  3. 调用适配器的 handle() 方法,内部将请求转发给对应的 Handler

Java SDK 中的适配器:

  • Arrays.asList() —— 数组适配为 List
  • InputStreamReader —— 字节流适配为字符流
  • Collections.enumeration() —— Collection 适配为 Enumeration
追问与易错

追问方向:

  • 类适配器和对象适配器区别?
  • Spring MVC 为什么需要 HandlerAdapter?
  • 和门面区别?

易错点:

  • ❌ 适配器就是封装——核心是接口转换
  • ❌ 不推荐用——遗留系统集成非常有用

💡 记忆锚点

万能充电转接头:你的三脚插头(旧接口)插不进两孔插座(目标接口),转接头(Adapter)两边各适配一个口。Spring MVC的HandlerAdapter就是这个转接头——把注解式/@Controller/HttpRequestHandler三种不同插头统一转成DispatcherServlet认识的两孔插座。