设计模式 || 适配器模式

Posted hill1126

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式 || 适配器模式相关的知识,希望对你有一定的参考价值。

  • 什么是适配器模式?

先从一个例子说起:你有一台Type-c接口的手机,某天你突然想买条高贵的Sony耳机体验是什么感觉。然后行兴高采烈买回来才发现,这个耳机的插头竟然是见鬼的3.5mm插头,你心里一顿***。此时你没钱再买一条耳机,更没有钱换一台手机。怎么办?能想到的办法就是买一条转接线,这条转接线为这两种类型的接口做了一个适配,使手机能把声音正确的输出到耳机当中。

由例子可以看出:适配器模式是为了解决两个不同的对象之间不兼容的问题,通过一个设配器的中间对象,而使双方能在一起配合工作。在上面例子中,耳机的3.5mm接口可以被当作被适配者(Adaptee),手机的Type-c接口可以被当作目标接口(Target),而那条转接线就是适配器(Adapter)。

  • 适配器模式代码展示

在这里我们再以笔记本的适配器为例,我们知道中国家用电压为220V,而笔记本的输入电压一般不会超过20V。这时,我们也需要一个电源适配器使得我们的笔记本能够正常工作。

首先,确定各个物件的身份。电源适配器:Adapter   家用电源:Adaptee   笔记本设备接口:Target

 1 /**
 2  * @author HILL
 3  * @version V1.0
 4  * @date 2019/7/8
 5  **/
 6 public class HousePower implements Power
 7 
 8     /**
 9      * 中国家庭用电电压为220伏
10      * @Author: HILL
11      * @date: 2019/7/8 15:07
12     **/
13     private static final int VOLTAGE = 220;
14 
15     /**
16      * @Author: HILL
17      * @date: 2019/7/8 15:08
18      * @return: int 中国家庭用电电压
19     **/
20     @Override
21     public int outPutPower() 
22         return VOLTAGE;
23     
24 
技术图片
 1 public interface Adapter 
 2 
 3     /**
 4      * 每个适配器有特定的转换电压
 5      * @Author: HILL
 6      * @date: 2019/7/9 14:18
 7      * @param: []
 8      * @return: int 返回特定的转换电压
 9     **/
10     int outConversionVoltage();
11 
笔记本需要的接口:Target

在这里,我们采用的是类适配器,即通过继承的方式完成两者之间的适配,这种方法没那么灵活,但是在编码方面比较方便快捷。

/**
 * @author HILL
 * @version V1.0
 * @date 2019/7/8
 **/
public class LapTopAdapter extends HousePower implements Adapter


    /**
     * TODO
     * @Author: HILL
     * @date: 2019/7/9 14:06
     * @param: []
     * @return: int 输出适配器转换后的电压值
    **/
    @Override
    public int outConversionVoltage() 
        //进行电压转换
        System.out.println("电压为"+super.outPutPower()+"开始转换");
        return super.outPutPower()/11;
    

很明显,上面的代码关系是这样的,我们的笔记本设备就可以通过Adapter接口完成电源的接入,成功运行。

技术图片

技术图片
 1 /**
 2  * @author HILL
 3  * @version V1.0
 4  * @date 2019/7/7
 5  *  TODO
 6  **/
 7 public class LapTop implements Device
 8 
 9     private Adapter adapter ;
10     private int VOLTAGE = 20;
11 
12     public LapTop(Adapter adapter) 
13         this.adapter = adapter;
14     
15 
16     @Override
17     public void startUse() 
18         if(adapter.outConversionVoltage()==VOLTAGE)
19             System.out.println("电压为"+VOLTAGE+"-----笔记本启动");
20         else
21             System.out.println("电压输入不正确,启动失败。异常电压为:"+adapter.outConversionVoltage());
22         
23     
24 
笔记本调用

 

  • 为什么要用适配器模式(优点)?

结论:

  1. 有利于Target与Adaptee的解耦,通过适配器能减少两者的关联性,那么在Adaptee做出修改的时候,我们只需要更换适配器,而不需要直接修改Target。
  2. 提供代码的复用性,既然可以简单的通过适配器就能完成功能,为何还要再造轮子?例如:既然能通过电源适配器转换电压,为何还要国家电网再供应20v的电压?
  3. 灵活易扩展,这里也是利用到了多态的特性,我们可以很灵活的更换一个适配器。这个自然可以理解。

 

在上面的例子中,可能利于理解适配器模式,但是不利于在开发中有自己的体会。所以接下来请看开发中框架用到的适配器模式。

  • 框架源码中的适配器模式

  1. SpringMVC中的适配器模式

我们可以看到springmvc的执行流程是如下图所示,至于具体的流程就不细说了,相信大家也懂。

技术图片

在这个流程图中,为什么DispatcherServlet不直接调用controller获取返回的结果,而选择在这两者间添加一个适配器(Adapter)呢?来看看SpringMVC的文档怎么说。有兴趣的可以自己去研究:https://docs.spring.io/spring/docs/5.1.8.RELEASE/spring-framework-reference/web.html#mvc-servlet-special-bean-types

这里我们直接贴出最重要的一句话。


 

Help the DispatcherServlet to invoke a handler mapped to a request, regardless of how the handler is actually invoked.
For example, invoking an annotated controller requires resolving annotations.
The main purpose of a HandlerAdapter is to shield the DispatcherServlet from such details.

 

HandlerAdapter最主要的目的是对DispatcherServlet屏蔽细节,然后让适配器实现具体细节,而DispatcherServlet是需要调用接口即可,不需要频繁的修改代码。试想一下,如果多出一个controller你就要添加一个调用的判断,那得多么的麻烦。

 1 //dispatcherServlet中的执行方法
 2   HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
 3 //执行方法,返回视图
 4  mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
 5 
 6 
 7 //假设直接调用
 8 if(controller  == LoginController)
 9      //do sth   
10 else if(controller == orderController)
11      //do sth  
12 else if(...)

 

其实还有很多框架也用到了适配器模式,尤其在安卓的开发当中。但是由于自己水平有限,博客就写道这里。

 

以上是关于设计模式 || 适配器模式的主要内容,如果未能解决你的问题,请参考以下文章

尚硅谷设计模式学习 --- [类适配器模式对象适配器模式接口适配器模式]

设计模式——适配器模式

设计模式 结构型模式 -- 适配器模式(概述类适配器模式对象适配器模式适配器模式适用场景JDK源码解析(I / O流))

设计模式:适配器模式(Adapter)

设计模式之(20)——适配器模式

设计模式之各种适配器