适配器模式

适配器模式是一个补偿模式,通常用来解决接口不相容的问题 ,又叫变压器模式,也叫包装模式

适配器模式最好在详细设计阶段不要考虑它,它不是为了解决还处在开发阶段的问题,而是解决正在服役的项目问题,该模式使用的主要场景是扩展应用

定义

将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配儿无法再一起工作的两个类能够在一起工作。

实现

适配器模式分为类结构型模式对象结构型模式两种,前者类之间的耦合度比后者高,且要求了解现有组件库中的相关组件的内部结构。

类适配器模式的类图

对象适配器模式的类图

Target目标接口,当前系统业务所期待的接口,它可以是抽象类或接口。

1
2
3
public interface Target {
void request();
}

Adaptee适配者类,它是被访问和适配的现存组件库中的组件接口。

1
2
3
4
5
public class Adaptee {
public void specificRequest() {
System.out.println("适配者中的业务代码被调用!");
}
}

Adapter适配器类,它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。

通过继承进行的适配, 叫做类适配器

1
2
3
4
5
6
7
8
9
10
11
public class ClassAdapter extends Adaptee implements Target {
@Override
public void request() {
super.specificRequest();
}
}

public static void main(String[] args) {
Target target = new ClassAdapter();
target.request();
}

通过关联关系进行的适配,叫做对象适配器。可釆用将现有组件库中已经实现的组件引入适配器类中,该类同时实现当前系统的业务接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class ObjectAdapter implements Target {
private Adaptee adaptee;

public ObjectAdapter(Adaptee adaptee) {
this.adaptee = adaptee;
}

@Override
public void request() {
adaptee.specificRequest();
}
}
public static void main(String[] args) {
Adaptee adaptee = new Adaptee();
Target target = new ObjectAdapter(adaptee);
target.request();
}

对象适配器和类适配器的区别是:类适配器是类间继承,对象适配器是对象的组合关系,对象适配器是通过类间的关联关系进行耦合的,因此在设计时就可以做到比较灵活;而类适配器就只能通过覆写源角色的方法进行扩展

优点

  • 可以让两个没有任何关系的类在一起运行
  • 增加了类的透明性,客户端通过适配器可以透明地调用目标接口
  • 提高了类的复用度,复用了现存的类,不需要修改原有代码而重用现有的适配者类
  • 将目标类和适配者类解耦,解决了目标类和适配者类接口不一致的问题
  • 灵活性非常好

缺点

  • 适配器编写过程需要结合业务场景全面考虑,可能会增加系统的复杂性
  • 增加代码阅读难度,降低代码可读性,过多使用适配器会使系统代码变得凌乱

应用场景

Spring AOP源码中适配器模式应用非常广泛,Advice就是来增强被代理类的功能,Advice 的类型主要有 BeforeAdviceAfterReturningAdviceThrowsAdvice

1
2
3
4
5
6
7
8
9
10
11
public interface Advice {
}

public interface AfterAdvice extends Advice {
}

public interface BeforeAdvice extends Advice {
}

public interface ThrowsAdvice extends AfterAdvice {
}

每种Advice都有对应的拦截器,即MethodBeforeAdviceInterceptorAfterReturningAdviceInterceptorThrowsAdviceInterceptor,不同类型的Interceptor,通过适配器统一对外提供接口,最终调用不同的 advice来实现被代理类的增强。

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
public interface Interceptor extends Advice {
}

public interface MethodInterceptor extends Interceptor {
@Nullable
Object invoke(@Nonnull MethodInvocation invocation) throws Throwable;
}

public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {
private final AfterReturningAdvice advice;

public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}

@Override
@Nullable
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
}

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
private final MethodBeforeAdvice advice;

public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}

@Override
@Nullable
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
}

Spring AOPAdvisorAdapter类有 4 个实现类,即 SimpleBeforeAdviceAdapterMethodBeforeAdviceAdapterAfterReturningAdviceAdapterThrowsAdviceAdapter

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
public interface AdvisorAdapter {
boolean supportsAdvice(Advice advice);

MethodInterceptor getInterceptor(Advisor advisor);
}

class AfterReturningAdviceAdapter implements AdvisorAdapter, Serializable {
@Override
public boolean supportsAdvice(Advice advice) {
return (advice instanceof AfterReturningAdvice);
}

@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
AfterReturningAdvice advice = (AfterReturningAdvice) advisor.getAdvice();
return new AfterReturningAdviceInterceptor(advice);
}
}

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
private final MethodBeforeAdvice advice;

public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}

@Override
@Nullable
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
}

class SimpleBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
@Override
public boolean supportsAdvice(Advice advice) {
return (advice instanceof SimpleBeforeAdvice);
}

@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
SimpleBeforeAdvice advice = (SimpleBeforeAdvice) advisor.getAdvice();
return new SimpleBeforeAdviceInterceptor(advice) ;
}
}

class ThrowsAdviceAdapter implements AdvisorAdapter, Serializable {
@Override
public boolean supportsAdvice(Advice advice) {
return (advice instanceof ThrowsAdvice);
}

@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
return new ThrowsAdviceInterceptor(advisor.getAdvice());
}
}

适配器模式在Spring MVC中的经典使用:

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
public interface HandlerAdapter {
boolean supports(Object handler);

@Nullable
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;

long getLastModified(HttpServletRequest request, Object handler);
}

public class SimpleServletHandlerAdapter implements HandlerAdapter {
@Override
public boolean supports(Object handler) {
return (handler instanceof Servlet);
}

@Override
@Nullable
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
((Servlet) handler).service(request, response);
return null;
}

@Override
public long getLastModified(HttpServletRequest request, Object handler) {
return -1;
}
}

public class HttpRequestHandlerAdapter implements HandlerAdapter {
@Override
public boolean supports(Object handler) {
return (handler instanceof HttpRequestHandler);
}

@Override
@Nullable
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
((HttpRequestHandler) handler).handleRequest(request, response);
return null;
}

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

MVC中体现在它的核心方法doDispatch方法中:

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
70
71
72
73
74
75
76
77
78
79
80
81
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);

// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}

// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

// Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}

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

// Actually invoke the handler.
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) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}

doDispatch()方法中调用了getHandlerAdapter()方法,在getHandlerAdapter()方法中循环调用supports()方法来判断是否兼容,循环迭代集合中的Adapter在初始化时早已被赋值。

1
2
3
4
5
6
7
8
9
10
11
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
for (HandlerAdapter adapter : this.handlerAdapters) {
if (adapter.supports(handler)) {
return adapter;
}
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}