设计模式源码git地址:design-pattern-src: 设计模式源码 (gitee.com)

  1. 什么是适配器模式
  2. 有几种适配器种类(了解)
  3. 应用场景
  4. 应用场景简单实现

img

什么是适配器模式

如图,将4个口最终转为一个口的能力,实现了很好的兼容

在程序对应中,将多个对象类型转为一个对象类型去调用方法

有几种适配器种类(了解)

类适配器

适配器类需要继承被适配器类(原来的东西)实现目标接口(转换得到的东西)

缺点:继承耦合性强,暴露了被适配器中的方法,好处是可以重写

对象适配器

不在继承,而是new一个实例,系统中尽量不使用继承关系,所以对象适配器是常用的一种

接口适配器

有些适配方法不需要全部实现,这种情况下可以使用一个抽象类实现接口中的全部方法,然后用匿名内部类的方式实现自己用的方法。类似于监听器类

应用场景

springmvc中的DispatcherServlet类中doDispatch方法中很清楚的出现了适配器的影子,只要把这块为什么作者使用适配器搞懂了,这个模式也就理解大半了,剩下的就是不断实践

1、首先根据传入的request来获取对应的handler

img

2、利用获取的handler获取适配器类adapter

img

3、利用该适配器调用对应的方法

img

为什么用适配器,直接根据handler调对应方法不就可以了?

①不知道获得的handler类型,需要判断,这本身也是一个适配的过程

常用的handler有:Controller,HttpRequestHandler、Servlet。而它们都属于不同的类型,调用的方法名也不同

img

②这里的handler被封装为了HandlerExecutionChain对象

这个类不知道获取的handler是什么类型,接口中虽然有获取handler方法,但返回类型为object。这时候需要用到handlerMapping来找对应的handler

img

③那为什么不用handlerMapping来调用方法?

基于单一职责,一个类只做一件事情, 这个类的作用就是处理请求与handler的对应关系,调用是有各自的handler去提供

④每个handler实现方式不同,但有个共同特点,传参都有request与response,那么就可以设置一个适配器类,传入相同的参数在给一个handler类型,来帮不同的handler提供一个统一的调用方法,起到适配的作用,可以联想以下扩展坞,假如你的电脑只支持c口,那么想用a口,hdmi口,就需要扩展坞,扩展坞的好处是方便,不管有什么口最终都可以转为一个口,而且好扩展

img

适配器类的好处

只需要给我一个handler类型的对象就可以,具体是什么不用管。

如果进行扩展,只需要添加适配器类就可以,调用方无需修改

不用适配器,能不能实现?

可以,首先同样得到handler,然后遍历if-else判断得到具体的handelr类型,在调各自的方法即可,但不方便扩展,每次都需要改调用方代码,违反开闭原则。所以适配器也可以看作高级版的if-else

适配器类在源码中是怎么实现的?

举个例子,如果为HttpRequestHandler类型,则强转为这个类型,然后调用

img

简单的MVC实现

uml类图

img

先画出类图,再根据类图实现代码

定义handler接口,实现该接口标识为handler

1
public interface Handler {}

HttpHandel

1
2
3
4
5
class HttpHandel implements Handler {
public void doHttpHandel() {
System.out.println("调用HttpHandel");
}
}

SimpleHandel

1
2
3
4
5
class SimpleHandel implements Handler {
public void doSimpleHandel() {
System.out.println("调用SimpleHandel");
}
}

定义adapter接口

1
2
3
4
public interface HandlerAdapter {
boolean supports(Object handler);
void handler(Object handler);
}

实现该接口

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

class SimpleHandlerAdapter implements HandlerAdapter {
@Override
public boolean supports(Object handler) {
return handler instanceof SimpleHandel;
}
@Override
public void handler(Object handler) {
((SimpleHandel)handler).doSimpleHandel();
}
}

模拟DispaterServlet类

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
public class DispatcherServletTest {

public static List<HandlerAdapter> handlerList = new ArrayList<>();

//做简化,spring中使用反射将adapter假如list中,如果扩展,只需要在配置文件中添加
public DispatcherServletTest() {
handlerList.add(new HttpHandlerAdapter());
handlerList.add(new SimpleHandlerAdapter());
}

/**
* 传参做简化,spring源码中根据request来获取handler
* @param handler
*/
protected void doDispatch(Handler handler) {
//根据不同的handler进行适配转换
HandlerAdapter adapter = this.getHandler(handler);
//进行方法调用
if (adapter != null) {
adapter.handler(handler);
}
}

protected HandlerAdapter getHandler(Handler handler) {
for (HandlerAdapter adapter : handlerList) {
if (adapter.supports(handler)) {
return adapter;
}
}
return null;
}

public static void main(String[] args) {
new DispatcherServletTest().doDispatch(new SimpleHandel());
}
}