适配器模式是一种结构型设计模式,用于在接口不兼容的情况下,让原本无法协作的类能够一起工作。适配器模式通过在两个不兼容的接口之间搭建桥梁,使得一个类的接口可以被客户端以期望的接口形式所使用。核心思想是将现有类的接口转换为客户端期望的接口。

适用场景

  • 接口不兼容
    当已有的类不能满足客户端的接口要求时,使用适配器进行接口转换。
  • 代码复用
    希望复用现有类的功能,但接口与目标接口不一致。
  • 引入第三方类库
    需要将第三方库的接口转换为自己系统的接口。
  • 遗留系统整合
    在新系统中需要使用旧系统的功能,但旧系统的接口不兼容。

实现方式

在适配器模式中,通常有以下角色:Target、Adaptee、Adapter和Client。各角色的说明如下表:

角色 功能说明
Target(目标接口) 定义了业务中需要使用方法,是对整体业务规则的约束。
Adaptee(被适配者) 业务中已有的接口或实例,需要基于该接口或实例对目标(Target)接口进行适配。
Adapter(适配器) Target与Adaptee之间的桥梁,完成从Adaptee到Target逻辑转换。
Client(请求者) 实际业务发起方,使用Target定义的方法进行业务处理。

Adapter依赖具体的Adaptee实现Target接口约定的规则,客户端面向Target接口编程屏蔽了不同具体适配器底层实现逻辑。业务执行过程中根据不同场景,选出合适的适配器进行业务逻辑处理。

适配模式根据具体实现有两种形式:类适配器与实例适配器。二者的核心区别在于:类适配器通过继承实现适配,而实例适配器通过组合实现适配。由于类适配器模式直接继承了被适配类,导致子类不够灵活。

类适配器

实现方式

  • 通过继承实现适配。
  • 适配器继承自 Adaptee 类,同时实现 Target 接口。

特点

  • 静态绑定:适配器与被适配者在编译时绑定。
  • 只能适配一个类:由于 Java 不支持多继承,适配器类只能继承一个被适配者类。
  • 更直接:继承机制允许适配器直接访问被适配者的功能。

适用场景

  • 单一被适配者:只有一个需要适配的类。
  • 无需修改被适配者:适配器直接继承被适配者,可以对其进行增强,而不修改其代码。
  • 不需要动态替换被适配者:被适配者类型是固定的。

UML图

实例适配器

实现方式

  • 通过组合实现适配。
  • 适配器持有 Adaptee 的实例,调用 Adaptee 的方法进行适配。

特点

  • 动态绑定:适配器和被适配者在运行时绑定。
  • 支持多被适配者:可以通过持有不同的 Adaptee 实例,实现适配不同的类。
  • 灵活性更高:可以动态替换 Adaptee 实例,而无需修改适配器代码。

适用场景

  • 多个被适配者:需要适配多个类,可以通过持有不同实例实现。
  • 需要动态替换被适配者:适配器可以在运行时使用不同的 Adaptee。
  • 无法修改被适配者:适配器通过组合而不是继承,避免对被适配者的直接依赖。

UML图

实例分析

下面通过适配器模式在实际代码中的具体应用对其进行分析,由于类适配器模式直接继承了被适配类,限制了其灵活性、可维护性和可扩展性,因此很少在实际中使用,这里不做过多分析。

Spring MVC的核心DispatcherServlet使用了适配器模式来支持多种类型的请求处理器。这主要体现在HandlerAdapter接口和其具体实现上,它负责将不同类型的Handler(控制器)统一适配为可以被DispatcherServlet调用的格式。解决了Spring MVC中支持多种控制器类型的需求,解耦了DispatcherServlet和具体控制器的实现。

实例UML图

代码实现

HandlerAdapter是适配器需要实现的目标接口,定义了目标业务需要用到的方法。

1
2
3
4
5
6
public interface HandlerAdapter {
// 判断当前适配器是否支持指定的Handler类型。
boolean supports(Object handler);
// 适配器实际调用Handler的方法,处理请求并返回ModelAndView。
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
}

具体的适配器实例需要实现HandlerAdapter接口,如SimpleControllerHandlerAdapter。在具体的适配器实例中,调用自身被适配类型响应方法进行实际的业务逻辑处理。如SimpleControllerHandlerAdapter中的Controller实例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
@Override
public boolean supports(Object handler) {
return (handler instanceof Controller);
}

@Override
@Nullable
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {

return ((Controller) handler).handleRequest(request, response);
}

@Override
@SuppressWarnings("deprecation")
public long getLastModified(HttpServletRequest request, Object handler) {
if (handler instanceof LastModified) {
return ((LastModified) handler).getLastModified(request);
}
return -1L;
}
}

在DispatcherServlet的doDispatch()方法中定义了整个业务处理流程,简化流程如下:

  • step1:从HandlerMapping中确定当前请求对应的Handler。
  • step2:根据Handler获取对应的HandlerAdapter。
  • step3:调用具体适配器,完成请求处理并返回结果。
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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;

WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

try {
ModelAndView mv = null;
Exception dispatchException = null;

try {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);

// step1:获取当前请求对应的Handler
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}

// step2:根据Handler获取对应的HandlerAdapter
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

// http get请求的缓存处理
String method = request.getMethod();
boolean isGet = HttpMethod.GET.matches(method);
if (isGet || HttpMethod.HEAD.matches(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}

if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}

// step3:调用具体适配器,完成请求处理并返回结果
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

if (asyncManager.isConcurrentHandlingStarted()) {
return;
}

applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
// 异常处理
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
// As of 4.3, we're processing Errors thrown from handler methods as well,
// making them available for @ExceptionHandler methods and other scenarios.
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
// 结果处理
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
// 异常处理
}

finally {
// 资源释放
}
}