java设计模式之适配器模式

适配器定义

将一个类的接口转成客户期望的另外一个接口。适配器模式使得原本由于接口不匹配而不能一起工作的那些类可以一起工作。

应用场景

上述这是官方的定义,用一个实际的生活案例来翻译一下适配器的应用场景,比如在中国有一个充电器的插头是3孔扁得,但是到了德国却变成另外一种2孔的了,我们总不能更换人家德国的插孔吧,怎么办?那就只好使用一个转换器了,通过这个转换器来适配我们的手机进行充电
在这里插入图片描述

适配器类型

适配器通常有类适配器,接口适配器,对象适配器,三种模式均可酌情使用

一、对象适配

对象为待适配的对象,也即目标对象,目标对象有一个需求,需要进行充电,但是它是标准的充电模式

提供一个带充电的方法

public class Phone {

    public void typecPhone() {
        System.out.println("标准的中国手机充电模式...");
    }

}

标准的输出接口

public interface CommonStandard {

    void commonUsb();

}

类适配模式需要继承目标方法同时实现一个标准输出的接口

public class GermanUsbV1 extends Phone implements CommonStandard {

    /**
     * 该方法表示最终需要将手机上的视频转换后输出到Vga上
     */
    @Override
    public void commonUsb() {
        typecPhone();
        System.out.println("接收到中国手机要充电的信息,信息转换成德国充电接口中...");
        System.out.println("信息已经转换成德国充电接口中,可以充电了");
    }

}

测试方法

 public static void main(String[] args) {

        //类适配器
        System.out.println("类适配器 -------------------");
        CommonStandard vga = new GermanUsbV1();
        vga.commonUsb();
        System.out.println("USB转换接口已经可以成功充电了");
}

在这里插入图片描述

二、对象适配

对象适配器和类适配器不同点在于,对象适配器直接持有一个对待适配对象的引用,因此我们只需要重新写一个类,引用目标适配类即可

public class GermanUsbV2 implements CommonStandard {

    private Phone phone;

    public GermanUsbV2(Phone phone){
        this.phone=phone;
    }

    @Override
    public void commonUsb() {
        if(phone != null){
            phone.typecPhone();
            System.out.println("接收到中国手机要充电的信息,信息转换成德国充电接口中...");
            System.out.println("信息已经转换成德国充电接口中,可以充电了");
        }
    }
}

测试代码

public static void main(String[] args) {

        //类适配器
        System.out.println("类适配器 -------------------");
        CommonStandard vga = new GermanUsbV1();
        vga.commonUsb();
        System.out.println("USB转换接口已经可以成功充电了");

        //第二种适配器用法
        System.out.println("-------------第二种适配器------------");
        GermanUsbV2 typec2Vga1 = new GermanUsbV2(new Phone());
        typec2Vga1.commonUsb();//适配器将typec转换成vga
        System.out.println("USB转换接口已经可以成功充电了");
        }

在这里插入图片描述

接口的适配,实际使用的并不是很多,有兴趣的同学可以自己再琢磨一下,下面来说一个具体的应用场景

三、springmvc中适配器的使用

SpringMvc中的适配器(HandlerAdapter)
SpringMVC中的适配器到底是解决以上哪个问题的呢?我们来一步一步看看源码,看看Spring是怎么做的

首先我们找到前端控制器DispatcherServlet可以把它理解为适配器模式中的Client,它的主要作用在于通过处理映射器(HandlerMapper)来找到相应的Handler(即Controlle(宽泛的概念Controller,以及HttpRequestHandler,Servlet,等等)r),并执行Controller中相应的方法并返回ModelAndView,

mappedHandler.getHandler()其实就是通过Spring容器中获取到的(宽泛的概念Controller,以及HttpRequestHandler,Servlet,等等)Controller

简单总结一下,就是前端发送一个请求过来,DispatcherServlet会根据请求类型和相应的参数决定要使用哪种类型的处理器,即handler,而handler再把具体的处理任务交给具体的实现类,但是这些处理器实现了共同的接口

public interface HandlerAdapter {
    boolean supports(Object var1);

    @Nullable
    ModelAndView handle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception;

    long getLastModified(HttpServletRequest var1, Object var2);
}

可以猜想springmvc对调用具体的handler处理请求逻辑可以是这样的

  • 初始化handler实现类集合
  • 根据传入请求的相关参数决定要使用哪一种处理器
  • 交给具体的处理器并返回结果

具体的实现代码基本上都在DispatcherServlet这个类中,有兴趣的同学可以研究下,下面模拟一下这个流程的代码实现:

自定义适配器接口

/**
 * 一个适配器接口
 */
public interface HandlerAdapter {

    String handle(String type);

}

提供多个类型的适配器,比如这里有controller类型的适配器和servlet类型的适配器

/**
 * controller类型的具体处理类
 */
public class ControllerHandler implements HandlerAdapter{

    @Override
    public String handle(String type) {
        return "我是controller处理的请求结果信息:" + type;
    }
}
/**
 * servlet类型的处理器
 */
public class ServletHandler implements HandlerAdapter{

    @Override
    public String handle(String type) {
        return "我是servlet处理的请求的响应接口";
    }

}

统一分发请求的入口类,即所有的请求都需要经过这个类的请求分发,类似DispatcherServlet某个功能

/**
 * 外部统一入口处理客户端请求信息的类
 */
public class GlobalHandleRequest {

    static List<HandlerAdapter> handlerAdapters = new ArrayList<>();

    public GlobalHandleRequest(){
        handlerAdapters.add(new ControllerHandler());
        handlerAdapters.add(new ServletHandler());
    }

    /**
     * 根据请求类型获取合适的处理器
     * @param handleType
     * @return
     */
    public HandlerAdapter getHandlerAdapter(String handleType) {
        // 获取适配器
        if (handleType.equals("controller")) {
            return handlerAdapters.get(0);
        }
        if (handleType.equals("servlet")) {
            return handlerAdapters.get(1);
        }
        return null;
    }

    //不同的适配器处理不同的请求结果
    public String getHandleResult(String handleType){
        HandlerAdapter handlerAdapter = getHandlerAdapter(handleType);
        return handlerAdapter.handle(handleType);
    }

}

写一个测试类

public class HandleTest {

    public static void main(String[] args) {
        GlobalHandleRequest handleRequest = new GlobalHandleRequest();
        String result = handleRequest.getHandleResult("servlet");
        System.out.println(result);
    }

}

在这里插入图片描述

这个应用虽然简单,但DispatcherServlet分发具体的handler时候大体也是这个思路,即存在适配器设计模式的思想在里面,有兴趣的同学可以研究下源码深入体会一下!本篇到此结束,最后感谢观看!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小码农叔叔

谢谢鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值