适配器模式:

基本概念
适配器模式(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

java 适配器模式实战 springmvc 适配器模式_spring

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);

源码难就难在不是一种设计模式,会有多种设计模式,继承,多态混合在一起,就比较难了