不雨花犹落 发表于 2021-9-2 13:08:37

设计模式---适配器模式

适配器模式



[*]适配器概念介绍
[*]介绍
[*]脚色
[*]工作原理
[*]3种适配器模式
[*]

[*]类适配器模式演示
[*]对象适配器模式
[*]

[*]对象适配器的优点
   
[*]接口适配器模式
[*]综合小案例---使用类适配器模式
[*]

[*]power--带转换的电压
[*]adapter--适配器
[*]FindAdapter--寻找合适的适配器
[*]测试


[*]适配器模式总结
[*]

[*]主要优点
[*]主要缺点
[*]适用场景

[*]spring MVC中的适配器模式
[*]

[*]springMVC处置惩罚请求流程
[*]请求处置惩罚方法中适配器模式部分源码探究
[*]总结

[*]参考文章

介绍

适配器模式(Adapter Pattern):将一个接口转换成客户渴望的另一个接口,使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。适配器模式既可以作为类布局型模式,也可以作为对象布局型模式。
在适配器模式中,我们通过增加一个新的适配器类来解决接口不兼容的问题,使得原本没有任何关系的类可以协同工作。
根据适配器类与适配者类的关系差别,适配器模式可分为对象适配器和类适配器两种,在对象适配器模式中,适配器与适配者之间是关联(聚合)关系;在类适配器模式中,适配器与适配者之间是继承(或实现)关系。
工作原理



[*] 适配器模式:将一个类的接口转换成另一种接口,让原本接口不兼容的类可以兼容;
[*] 从用户的角度看不到被适配者;
[*] 用户调用适配器转化出来的目标接口方法,适配器再调用被适配者的相关接口方法;
类适配器模式演示

以生存中充电器为例,充电器本身相当于适配者 (Adapter),220V 交换电相当于被适配者,我们的目标(target) 想把220V交换电转成5V直流电
要适配的类,即需要将220v电压转化为5v电压
//中国的电压220V
public class ChinaPower
{
    private final Integer outPut=220;
    public Integer getOutPut() {
      return outPut;
    }
} 适配器接口,只负责定义转化需要使用的业务逻辑方法,具体实现交由适配器类完成
//将电压转化为5v---适配接口
public interface TransTo5V
{
    Integer transTo5V();
} 适配器类,继承了ChinaPower,并实现了适配器接口,负责实现讲220v电压转化为5v的具体业务逻辑代码实现
//适配器类---实现适配器接口
public class ChinaAdapter extends ChinaPower implements TransTo5V
{
    //将220v电压转换为5v的
    @Override
    public Integer transTo5V()
    {
      //获得被适配类,即我们需要将220v电压转化为5v返回
      Integer output=super.getOutPut();
      //进行电压转换操作
      return output/44;
    }
} Phone类,需要用到适配器举行兼容,这样才可以充电
//手机需要5v的电压进行充电
public class Phone
{
    //通过适配器获得5v的电压
    public void charging(ChinaAdapter chinaAdapter)
    {
      if(5==chinaAdapter.transTo5V())
      {
            System.out.println("得到5v,充电中...");
      }
      else
      {
            System.out.println("电压过高,手机压力过大");
      }

    }
} 充电测试
public class test
{
    @Test
    public void test()
    {
      Phone p=new Phone();
      p.charging(new ChinaAdapter());
    }
}
接口适配器模式



[*] 接口适配器模式(Default Adapter Pattern),也叫缺省适配器模式;
[*] 核心思绪:当不需要全部实现接口提供的方法时,可先设计一个抽象类实现接口,并为该接口中每个方法提供一个默认实现(空方法),该抽象类的子类可有选择地覆盖父类的某些方法来实现需求;
[*] 适用于一个接口不想使用其所有的方法的情况;
定义一个适配器接口:
//适配器类---实现适配器接口
public class ChinaAdapter implements TransTo5V
{
    private ChinaPower chinaPower;
    //通过构造器,完成赋值
    public ChinaAdapter(ChinaPower chinaPower)
    {
   this.chinaPower=chinaPower;   
    }
    //将220v电压转换为5v的
    @Override
    public Integer transTo5V()
    {
      //获得被适配类,即我们需要将220v电压转化为5v返回
      Integer output=chinaPower.getOutPut();
      //进行电压转换操作
      return output/44;
    }
} 抽象类 AbsAdapter 将 InterfaceTest 的方法举行默认实现,当子类需要使用适配器接口中的某个方法,而不是全部方法时,就可以通过继承抽象类,来完成对需要使用的特定方法重写操作即可,无需实现适配器接口里面的全部方法
public class test
{
    @Test
    public void test()
    {
      Phone p=new Phone();
      p.charging(new ChinaAdapter(new ChinaPower()));
    }
} Client 调用接口,重写适配器抽象类方法
public interface InterfaceTest {
        public void m1();
        public void m2();
        public void m3();
        public void m4();
} 适配器模式总结

主要优点



[*] 将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,无须修改原有布局。
[*] 增加了类的透明性和复用性,将具体的业务实现过程封装在适配者类中,对于客户端类而言是透明的,而且提高了适配者的复用性,同一个适配者类可以在多个差别的系统中复用。
[*] 机动性和扩展性都非常好,通过使用配置文件,可以很方便地更换适配器,也可以在不修改原有代码的基础上增加新的适配器类,完全符合“开闭原则”。
具体来说,类适配器模式还有如下优点:


[*] 由于适配器类是适配者类(适配器接口或适配器接口实现的抽象类)的子类,因此可以在适配器类中置换一些适配者(适配器接口或适配器接口实现的抽象类)的方法,使得适配器的机动性更强。
[*] 一个对象适配器可以把多个差别的适配者(适配器接口或适配器接口实现的抽象类)适配到同一个目标;
[*] 可以适配一个适配者的子类,由于适配器和适配者(适配器接口或适配器接口实现的抽象类)之间是关联关系,根据“里氏代换原则”,适配者(适配器接口或适配器接口实现的抽象类)的子类也可通过该适配器举行适配。
适用场景



[*] 系统需要使用一些现有的类,而这些类的接口(如方法名)不符合系统的需要,甚至没有这些类的源代码。
[*] 想创建一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些大概在将来引进的类一起工作。
请求处置惩罚方法中适配器模式部分源码探究


Spring MVC中的适配器模式主要用于执行目标 Controller 中的请求处置惩罚方法。
在Spring MVC中,DispatcherServlet 作为用户,HandlerAdapter 作为渴望接口(适配器接口),具体的适配器实现类用于对目标类举行适配,Controller 作为需要适配的类。
为什么要在 Spring MVC 中使用适配器模式?Spring MVC 中的 Controller 种类众多,差别类型的 Controller 通过差别的方法来对请求举行处置惩罚。如果不利用适配器模式的话,DispatcherServlet 直接获取对应类型的 Controller,需要的自行来判定,像下面这段代码一样:
public abstract class AbsAdapter implements InterfaceTest {

        //默认实现
        public void m1() {}
        public void m2() {}
        public void m3() {}
        public void m4() {}
} 这样假设如果我们增加一个 HardController,就要在代码中加入一行 if(mappedHandler.getHandler() instanceof HardController),这种形式就使得步伐难以维护,也违反了设计模式中的开闭原则 – 对扩展开放,对修改关闭。
我们来看看源码,首先是适配器接口 HandlerAdapter
public class Client {
        public static void main(String[] args) {
               
                AbsAdapter absAdapter = new AbsAdapter() {
                        //只需要去覆盖我们 需要使用 接口方法
                        @Override
                        public void m1() {
                                System.out.println("使用了m1的方法");
                        }
                };
               
                absAdapter.m1();
        }
} 现该接口的适配器每一个 Controller 都有一个适配器与之对应,这样的话,每自定义一个 Controller 需要定义一个实现 HandlerAdapter 的适配器。
springmvc 中提供的 Controller 实现类有如下:

springmvc 中提供的 HandlerAdapter 实现类如下

HttpRequestHandlerAdapter 这个适配器代码如下:
public interface Power
{
   Integer getOutPut();
} 当Spring容器启动后,会将所有定义好的适配器对象存放在一个List集合中,当一个请求来暂时,DispatcherServlet 会通过 handler 的类型找到对应适配器,并将该适配器对象返回给用户,然后就可以同一通过适配器的 hanle() 方法来调用 Controller 中的用于处置惩罚请求的方法。
//中国的电压220V
public class ChinaPower implements Power
{
    private final Integer outPut=220;
    @Override
    public Integer getOutPut() {
      return outPut;
    }
} 通过适配器模式我们将所有的 controller 同一交给 HandlerAdapter 处置惩罚,免去了写大量的 if-else 语句对 Controller 举行判定,也更利于扩展新的 Controller 类型。
参考文章

设计模式 8 - 适配器模式与springmvc源码分析
设计模式 | 适配器模式及典型应用
适配器模式(SpringMVC源码分析)
设计模式 | 适配器模式及典型应用

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: 设计模式---适配器模式