java设计模式(二)之适配器模式

适配器的概念:

将一个类的接口转换成客户期望的另一个接口。使得原本由于接口不匹配而不能一起工作的类可以一起工作。

客户期望的接口A是供应接口,而提供的接口B为需求接口。适配器的适配就是指 需求“适配”供应。

假如我的手机充电口是type-c类型的,但我只有一根传统的Micro USB接口的数据线,怎么办?

type-c类型的接口就是需求接口,Micro USB类型的接口是供应接口,想让需求匹配供应,就需要有一个适配器。

适配器的三种实现方式:

1. 类适配器

当需要把一个已经实现了接口A的类A转换成 能 实现接口B的类时,可使用类适配器模式。

注意:类A是已经设计好的,不能改变。可以把接口A看作需求接口,接口B看作供应接口。

通过继承特性实现适配器功能。创建一个新类,实现接口,继承原有的类即可。

//  供应接口
public interface MicroUsb {    
    public void microUsb();
}

//  需求接口
public interface TypeC {    
    public void typeC();
}

//  需求实现类
public class Phone implements TypeC{   
    public void typeC() {
        System.out.println("Type-C接口");
    }
}

//  适配器
public class Adapter extends Phone implements MicroUsb{    
    public void microUsb() {        
        typeC();    
    }
}

//  测试类
public class Test {   
    public static void main(String[] args) {
        MicroUsb microUsb = new Adapter();
        microUsb.microUsb();   
    }
}

2. 对象适配器

希望将接口A的实现类A的对象转换满足接口B对象时,可使用对象适配器的方式。

通过组合方式实现适配器功能。将接口A的对象封装在适配器中,同时适配器继承接口B,便可将接口A类型转换为接口B类型。

//  供应接口
public interface MicroUsb {
    public void microUsb();
}

//  需求接口
public interface TypeC {
    public void typeC();
}

//  需求实现类
public class Phone implements TypeC{
    public void typeC() {
        System.out.println("Type-C接口");
    }
}

//  适配器
public class Adapter implements MicroUsb{
    private TypeC typeC;
    public Adapter(TypeC typeC){
        this.typeC=typeC;
    }
   @Override
    public void microUsb() {
       typeC.isTypeC();
    }
}

//  测试类
public class Test {
    public static void main(String[] args) {
        TypeC typeC = new Phone();
        MicroUsb microUsb = new Adapter(typeC);
        microUsb.microUsb();
    }
}

3. 接口适配器

个很大的接口,包含很多方法,当不希望实现接口中的所有方法时,可创建一个抽象类继承接口,但方法实现都是空的,实现类可继承这个抽象类实现了适配器的功能。

构建一个情景:日常用的转换器有很多种类型的接口,比如type-C,VGA,Hdmi,可以把这些类型都放在一个大的接口中,当我只需type-C和VGA类型的转换器时,继承相关的类即可。

//  接口类
public interface AllPorts {
    public void isTypeC();
    public void isVGA();
    public void isHdmi();}
//  适配器的框架
public abstract class Adapter implements AllPorts{
    @Override    public void isTypeC() { }
    @Override    public void isVGA() { }    
    @Override    public void isHdmi() { }
}
//  适配器类
public class TypecToVGA extends Adapter{
    @Override    public void isTypeC() {
        System.out.println("信号从TypeC接口进入");
    }
    @Override
    public void isVGA() {
        System.out.println("信号从VGA接口出");
    }
}
//  测试类
public class Test {
    public static void main(String[] args) {
        TypecToVGA typecToVGA = new TypecToVGA();
        typecToVGA.isTypeC();
        typecToVGA.isVGA();
    }
}

适配器模式在Spring MVC中的应用:

HandlerMapping 是可以有多种实现的,Spring会遍历这些具体的实现类,判断哪一个能够根据当前request产生一个handler,因而对于HandlerAdapter而言,其是不知道当前获取到的 handler 具体是什么形式的,不同的HandlerMapping 产生的handler形式是不一样的。

DispatcherServlet 会根据 HandlerMapping 传过来的 handler与HandlerAdapter的实现类一一匹配,如果找到了其中一种HandlerAdapter支持传过来的 handler 类型,那么该HandlerAdapter会调用自己的 handle 方法处理该请求。

首先看一下HandlerAdapter接口的内部方法:

public interface HandlerAdapter {
    
    // 判断当前 HandlerAdapter 是否支持处理该handle
    boolean supports(Object var1);

    // 利用handle处理请求
    @Nullable
    ModelAndView handle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception;

    long getLastModified(HttpServletRequest var1, Object var2);
}

HandlerAdapter的实现类:

1. HttpRequestHandlerAdapter ,处理HttpRequestHandler类型的handler

public class HttpRequestHandlerAdapter implements HandlerAdapter {
    public HttpRequestHandlerAdapter() {
    }

    public boolean supports(Object handler) {
        return handler instanceof HttpRequestHandler;
    }

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

2. SimpleServletHandlerAdapter,处理Servlet类型的handler

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

3.  SimpleControllerHandlerAdapter是Controller处理适配器,适配实现了Controller接口或Controller接口子类的处理器,比如我们自己写的Controller来继承MultiActionController.

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

4.AbstractHandlerMethodAdapter

在这里 AbstractHandlerMethodAdapter 只有一个实现子类就是 RequestMappingHandlerAdapter,首先我们来看下其内部是怎么来实现判断 supports(..) 是否支持该 handler 以及 handler 解析方法 handle 

public abstract class AbstractHandlerMethodAdapter extends WebContentGenerator implements HandlerAdapter, Ordered {
    private int order = 2147483647;

    public AbstractHandlerMethodAdapter() {
        super(false);
    }

    public void setOrder(int order) {
        this.order = order;
    }

    public int getOrder() {
        return this.order;
    }

    // 由子类实现是否支持解析该 HandlerMethod 对象
    public final boolean supports(Object handler) {
        return handler instanceof HandlerMethod && this.supportsInternal((HandlerMethod)handler);
    }

    protected abstract boolean supportsInternal(HandlerMethod var1);

    // handle解析方法
    @Nullable
    public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return this.handleInternal(request, response, (HandlerMethod)handler);
    }
    // 抽象方法,由子类实现具体的HandleMethod解析逻辑
    @Nullable
    protected abstract ModelAndView handleInternal(HttpServletRequest var1, HttpServletResponse var2, HandlerMethod var3) throws Exception;

 

©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页