定义
在计算机编程中,适配器模式(有时候也称包装样式)将一个类的接口适配成用户所期待的。一个适配允许通常因为接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存在的类中。
- 对象适配器模式
在这种适配器模式中,适配器容纳一个它包裹的类的实例。在这种情况下,适配器调用被包裹对象的物理实体。 - 类适配器模式
这种适配器模式下,适配器继承自已实现的类(一般多重继承)。
示例
对象适配器
- 客户所期待的目标类
java
public interface Target {
void doSomething();
}
- 适配器
java
public class Adapter implements Target {
private Adaptee adaptee;
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void doSomething() {
adaptee.doSpecific();
}
}
- 需要适配的类
java
public class Adaptee {
void doSpecific() {
System.out.println("Adaptee doSpecific execute!");
}
}
- 测试
java
public class ObjTest {
public static void main(String[] args) {
Adaptee adaptee = new Adaptee();
Adapter adapter = new Adapter(adaptee);
adapter.doSomething();
}
}
类适配器模式
- 客户所期待的目标类
java
public interface Target {
void doSomething();
}
- 适配器
java
public class Adapter extends Adaptee implements Target {
@Override
public void doSomething() {
doSpecific();
}
}
- 需要适配的类
java
public class Adaptee {
void doSpecific() {
System.out.println("Adaptee doSpecific execute!");
}
}
- 测试
java
public class ClazzTest {
public static void main(String[] args) {
Adapter adapter = new Adapter();
adapter.doSomething();
}
}
源码级应用场景
- 类适配器:java.util.Arrays#asList
java
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
Arrays#asList接收一个对象将它转换成一个java.util.ArrayList,它继承 AbstractList,所以JDK在Arrays里面也定义了一个java.util.Arrays.ArrayList继承AbstractList
在这里java.util.List是客户所需要的目标类,java.util.Arrays.ArrayList是适配器,需要是适配的类就是该方法接收的泛型。
- 对象适配器:java.util.concurrent.FutureTask
java
public class FutureTask<V> implements RunnableFuture<V> {
private Callable<V> callable;
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW;
}
}
线程池提供了两种提交任务的方法,分别是submit和execute,submit提交Callable任务,execute提交Runnable任务,而submit最终通过execute方法执行任务,所以在提交Callable任务之前调用newTaskFor(),它使用FutureTask适配器将Callable对象任务适配为Runnable。
java
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);
return ftask;
}
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
return new FutureTask<T>(callable);
}
- SpringMVC:org.springframework.web.servlet.HandlerAdapter
java
public interface HandlerAdapter {
// 判断是否支持某个具体的适配器
boolean supports(Object handler);
// 处理请求,执行目标类的方法
@Nullable
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
}
在SpringMVC中,HandlerAdapter适配器是一个接口,它有5个适配器实现,熟知的就是RequestMappingHandlerAdapter,他是适配那些在类或者方法上被@RequestMapping注解的Controller。
当SpringMVC接收到一个请求后,会交给DispatcherServlet的doDispatch()处理
- 首先根据request请求查找对应的处理器handler,将它封装为HandlerExecutionChain(包含HandlerMethod或者servlet等和拦截器interceptors)
- 根据HandlerExecutionChain的属性handle(即HandlerMethod)查找对应适配器,由于handler是HandlerMethod类型,所以找到了RequestMappingHandlerAdapter适配器
- 调用RequestMappingHandlerAdapter.handler()方法处理请求,最后反射执行Controller对应的方法
SpringMVC适配器小结
在这里客户端是DispatcherServlet,它想要的目标类是ModelAndView,被适配的是handler。