适配器模式:
基本概念
适配器模式(Adapter Pattern):将某个类的接口转换成客户端期望的另一个接口,让原本因接口不匹配不能一起工作的两个类可以协同工作。其别名为包装器(Wrapper),从用户的角度看不到被适配者,用户调用适配器转化出来的目标接口方法,适配器再调用被适配者的相关接口方法;;
适配器模式属于结构型模式;
主要分为三类:类适配器模式、对象适配器模式、接口适配器模式;
适配器的4个角色
1、目标(Target)
定义一个客户端使用的特定接口。
2、客户端(Client)
使用目标接口,与和目标接口一致的对象合作。
3、被适配者(Adaptee)
一个现存需要适配的接口。
4、适配器(Adapter)
负责将Adaptee的接口转换为Target的接口。适配器是一个具体的类,这是该模式的核心。
适配器模式:
Target( 目标抽象类) : 定义客户所需接口, 可以是一个抽象类或接口, 也可以是具体类
Adapter( 适配器类) : 可以调用另一个接口, 作为一个转换器, 对Adaptee和Target进行适配, 适配器类是适配器模式的核心, 在对象适配器中, 它通过继承Target并关联一个Adaptee对象使二者产生联系
Adaptee( 适配者类) : 被适配的角色, 它定义了一个已经存在的接口, 这个接口需要适配, 适配者类一般是一个具体类, 包含了客户希望使用的业务方法, 在某些情况下可能没有适配者类的源代码
优点
可以让任何两个没有关联的类一起运行;
增加了类的透明性;
提高了类的复用度;
灵活性非常好;
缺点
过多使用适配器会使系统非常凌乱;
由于java是单继承的,所以只能适配一个适配器类,而且目标类必须是抽象的;
只有碰到无法改变原有设计和代码的情况下,才会考虑适配器模式;
使用场景:
1、系统需要使用现有的类,从而类的接口不符合系统的需要。
2、想建立一个可以重复使用的类,用于一些彼此之间没有太大关联的一些类。
3、通过接口转换,将一个类插入另一个类中。
类适配器模式:
类适配器模式的代码如下。
package adapter;
//目标接口
interface Target
{
public void request();
}
//适配者接口
class Adaptee
{
public void specificRequest()
{
System.out.println("适配者中的业务代码被调用!");
}
}
//类适配器类
class ClassAdapter extends Adaptee implements Target
{
public void request()
{
specificRequest();
}
}
//客户端代码
public class ClassAdapterTest
{
public static void main(String[] args)
{
System.out.println("类适配器模式测试:");
Target target = new ClassAdapter();
target.request();
}
}
对象适配器模式:
对象适配器模式的代码如下。
package adapter;
//对象适配器类
class ObjectAdapter implements Target
{
private Adaptee adaptee;
public ObjectAdapter(Adaptee adaptee)
{
this.adaptee=adaptee;
}
public void request()
{
adaptee.specificRequest();
}
}
//客户端代码
public class ObjectAdapterTest
{
public static void main(String[] args)
{
System.out.println("对象适配器模式测试:");
Adaptee adaptee = new Adaptee();
Target target = new ObjectAdapter(adaptee);
target.request();
}
}
说明:对象适配器模式中的“目标接口”和“适配者类”的代码同类适配器模式一样,只要修改适配器类和客户端的代码即可。
程序的运行结果如下:对象适配器模式测试:
适配者中的业务代码被调用!
分析下spring mvc源码中适配器模式
springmvc中的适配器模式为对象适配器,下面看下源码:
Target( 目标抽象类):HandlerAdapter
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.springframework.web.servlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.lang.Nullable;
public interface HandlerAdapter {
//(实际上controller,根据controller类型选择对应的handler)
boolean supports(Object var1);
// 抽象方法,handler的执行方法,放在接口由handleradapter实现
@Nullable
ModelAndView handle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception;
//最后一次更改
long getLastModified(HttpServletRequest var1, Object var2);
}
适配器(Adapter): 就是对象接口的实现类
它的实现类有6个,其中RequestMapperingHandlerAdapter是我们最常使用的,代表被@RequestMapping修饰的controller使用这个HandlerAdapter
spring mvc执行流程中 gethandler部分(这里传入的mappedHandler.getHandler(),就是广意的controller(宽泛的概念Controller,以及HttpRequestHandler,Servlet,等等),mappedHandler就是handlermapping返回的HandlerExecutionChain调用链,包括了handler(controller)和intercepers) ,这里可以看做客户端(Client)
HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
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;
}
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
首先看下 this.getHandlerAdapter
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
// 如果this.handlerAdapters 不为空,就对this.handlerAdapters 做个循环,
if (this.handlerAdapters != null) {
Iterator var2 = this.handlerAdapters.iterator();
while(var2.hasNext()) {
HandlerAdapter adapter = (HandlerAdapter)var2.next();
调用this.handlerAdapters 中support方法,传入handler(实际上就是controller),是否统一类型,是就返回对应的adapter
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");
}
案例一:
以 RequestMappingHandlerAdapter为例子,继承AbstractHandlerMethodAdapter,AbstractHandlerMethodAdapter实现了HandlerAdapter
supports方法在AbstractHandlerMethodAdapter中实现,supportsInternal在RequestMappingHandlerAdapter默认返回true,只需要比较handler是否为HandlerMethod 方法即可
public final boolean supports(Object handler) {
return handler instanceof HandlerMethod && this.supportsInternal((HandlerMethod)handler);
}
protected abstract boolean supportsInternal(HandlerMethod var1);
调用handle方法,然后调用handleInternal ,这个实现方法在子类RequestMappingHandlerAdapter中实现 ,这里传入的对象Object handler就是Adaptee( 适配者类)
@Nullable
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return this.handleInternal(request, response, (HandlerMethod)handler);
}
@Nullable
protected abstract ModelAndView handleInternal(HttpServletRequest var1, HttpServletResponse var2, HandlerMethod var3) throws Exception;
RequestMappingHandlerAdapter
protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
this.checkRequest(request);
ModelAndView mav;
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized(mutex) {
mav = this.invokeHandlerMethod(request, response, handlerMethod);
}
} else {
mav = this.invokeHandlerMethod(request, response, handlerMethod);
}
} else {
mav = this.invokeHandlerMethod(request, response, handlerMethod);
}
if (!response.containsHeader("Cache-Control")) {
if (this.getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
this.applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
} else {
this.prepareResponse(response);
}
}
return mav;
}
案例二:
SimpleControllerHandlerAdapter 对象适配器, 实现HandlerAdapter,handle方法传入 handler(controller对象),然后调用Controller(这里的Controller又是一个接口,使用其实现子类的方法)的handleRequest方法,这里传入的对象Object handler就是Adaptee( 适配者类)
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.springframework.web.servlet.mvc;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.ModelAndView;
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
public SimpleControllerHandlerAdapter() {
}
public boolean supports(Object handler) {
return handler instanceof Controller;
}
@Nullable
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return ((Controller)handler).handleRequest(request, response);
}
public long getLastModified(HttpServletRequest request, Object handler) {
return handler instanceof LastModified ? ((LastModified)handler).getLastModified(request) : -1L;
}
}
案例三:
SimpleServletHandlerAdapter 对象适配器 实现HandlerAdapter,handle方法传入 handler(controller对象),然后调用Controller(这里的Controller又是一个接口,使用其实现子类的方法)的service方法, 这里传入的对象Object handler就是Adaptee( 适配者类)
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.springframework.web.servlet.handler;
import javax.servlet.Servlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.ModelAndView;
public class SimpleServletHandlerAdapter implements HandlerAdapter {
public SimpleServletHandlerAdapter() {
}
public boolean supports(Object handler) {
return handler instanceof Servlet;
}
@Nullable
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
((Servlet)handler).service(request, response);
return null;
}
public long getLastModified(HttpServletRequest request, Object handler) {
return -1L;
}
}
经过上面源码分析可知:适配器模式主要是要调用现存代码的方法,但是现在类又和接口不匹配,所以就使用适配器模式,在中间加一层,去调用我们所需要的方法
然后会有人疑问:这里用多态也能实现啊,只要新增的适配器实现(例如SimpleServletHandlerAdapter)handlerAdapter,重写方法我就能调用handle啊,确实,这样的确能实现,但是我们在看下适配器模式的应用场景
适用场景:
1、已经存在的类的接口不符合我们的需求;
2、创建一个可以复用的类,使得该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作;
3、在不对每一个都进行子类化以匹配它们的接口的情况下,使用一些已经存在的子类。
我们对照对象适配器,我们其实要调用的不是适配器(例如SimpleServletHandlerAdapter)里面的handle方法,真正想要用的是已存在的类
handle里面类servlet的service方法,如果仅仅是多态的话,我们就必须在适配器里面handle方法里面写具体的实现了,有了适配器,我就可以复用现有的类里面的方法,而不用再去重复写实现,只需要一个适配器即可,其实适配器真的理解起来就很简单:就是利用了多态,在实现方法中传入已经存在的类(即适配者),然后调用适配者的方法
((Servlet)handler).service(request, response);
源码难就难在不是一种设计模式,会有多种设计模式,继承,多态混合在一起,就比较难了