当前位置: 首页 >  网技达人 >  适配器模式

适配器模式

导读:适配器模式.基本介绍.1.适配器模式(Adapter Pattern)将某个类的接口(方法)转换成客户期望的另一个接口(方法)表示,主要目的是兼容性,让原本因为方法不匹配的,不能一起工作的两个类可以协同工作。别名叫包装器(Wrapper)。.2.适配器模式属于结构模式。.3.主要

适配器模式

基本介绍

  • 1.适配器模式(Adapter Pattern)将某个类的接口(方法)转换成客户期望的另一个接口(方法)表示,主要目的是兼容性,让原本因为方法不匹配的,不能一起工作的两个类可以协同工作。别名叫包装器(Wrapper)。
  • 2.适配器模式属于结构模式。
  • 3.主要有三种形式,类适配器模式,对象适配器模式,接口适配器模式。

类适配器模式

介绍

Adapter类,通过继承src类,实现dest接口,完成src -> dest的适配。

应用实例
  • 1.以手机充电为例,充电器本身相当于Adapter类,220V的交流电相当于src(被适配者),我们的dest(目标)是5V直流电。
  • 2.类图
代码

案例只是展示这种思想,无实际意义。

public class Voltage220V {

    public int output220V(){
        int voltage = 220;
        System.out.println("电压" + voltage + "V");
        return voltage;
    }
}
public interface Voltage5V {
    public int output5V();
}
public class Adapter extends Voltage220V implements Voltage5V{
    @Override
    public int output5V() {
        int src = this.output220V();
        int dest = src / 44;//转成5v
        return dest;
    }
}
public class Phone {

    public void charging(Voltage5V v){
        if(v.output5V() == 5){
            System.out.println("电压为5V,可以充电");
        }else if(v.output5V() > 5){
            System.out.println("电压大于5V,不能充电");
        }
    }
}
//测试
public class Client {
    public static void main(String[] args) {
        System.out.println("类适配器模式");
        new Phone().charging(new Adapter());
    }
}
注意事项和细节
  • 1.Java是单继承机制,所以类适配器需要继承src类这一点是一个缺点,还要求dest必须是接口,有一定局限性。
  • 2.Adapter类,会继承src类的所有方法,增加了使用成本。
  • 3.由于继承了src类,所以它可以根据需求重写src类的方法,使得Adapter类的灵活性增强了。

对象适配器模式

介绍
  • 1.基本思路和类的适配器模式相同,只是将Adapter类做修改,不是继承src类,而是持有src类的实例,解决兼容性的问题。即持有src类,实现dest接口,完成src -> dest的适配。
  • 2.根据合成复用原则,尽量使用关联关系替代继承关系。
  • 3.对象适配器模式是适配器模式常用的一种。
应用实例

用对象适配器模式,完成手机充电案例

public class Voltage220V {
    public int output220V(){
        int voltage = 220;
        System.out.println("输出电压" + voltage + "V");
        return voltage;
    }
}
public interface Voltage5V {
    public int output5V();
}
public class Phone {
    public void charging(Voltage5V v){
        if(v.output5V() == 5){
            System.out.println("电压为5V,可以充电");
        }else if(v.output5V() > 5){
            System.out.println("电压大于5V,不能充电");
        }
    }
}
public class Adapter implements Voltage5V {

    private Voltage220V voltage220V;

    public Adapter(){}

    public Adapter(Voltage220V voltage220V){
        this.voltage220V = voltage220V;
    }

    public void setVoltage220V(Voltage220V voltage220V) {
        this.voltage220V = voltage220V;
    }

    @Override
    public int output5V() {
        int src = voltage220V.output220V();
        int dest = src / 44;
        System.out.println("进行电压适配" + src + "->" + dest);
        return dest;
    }
}
public class Client {
    public static void main(String[] args) {
        System.out.println("对象适配器模式");
        Phone phone = new Phone();
        Adapter adapter = new Adapter(new Voltage220V());
        phone.charging(adapter);
    }
}
注意事项和细节
  • 1.对象适配器和类适配器是同一种思想,只是实现方式不同。根据合成复用原则,使用组合代替继承,所以它解决了类适配器必须继承src的局限性问题,也不再要求dest是接口。
  • 2.使用成本更低,更灵活。

接口适配器模式

介绍
  • 1.当不需要全部实现接口提供的方法时,可以设计一个抽象类实现接口,并为该接口中每个方法提供一个默认的实现(空方法),那么该抽象类的子类可以有选择性的重写某些方法。
  • 2.适用于一个接口不想使用其所有方法的情况
  • 3.接口适配器模式,也被称为默认适配器模式。
应用实例
  • 1.Android中的属性动画ValueAnimator类可以通过addListener(AnimatorListener listener)方法添加监听器,常规方法如下右图。

  • 2.不想实现Animator.AnimatorListener接口的全部方法,我们只想监听onAnimationStart 如下 下图写。

  • 3.AnimatorListenerAdapter类,就是一个接口适配器,代码如下 右图。

  • 4.AnimatorListener是一个接口。

  • 5.程序里的匿名内部类就是AnimatorListener的具体实现类。
    Java中的匿名内部类,类似接口适配器模式。

适配器模式在SpringMVC中的源码分析

  • 1.SpringMVC中的HandlerAdapter,就是用了适配器模式。

  • 2.使用HandlerAdapter的原因分析。Handler(controller,处理器)的类型不同,有多重实现方式,那么调用方式就不是确定的,如果需要直接调用Controller方法,需要调用时,就要使用很多的if else分支语句,进行判断,哪一种子类执行。这样的写法,如果要扩展controller,就要修改原来的代码,违背了ocp。

  • 3.代码分析

    //DispatchServlet类中得doDispatch(HttpServletRequest request, HttpServletResponse response)方法 部分源码 HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null;//参数定义 // Determine handler for the current request. mappedHandler = getHandler(processedRequest);//根据请求获取 对应的HandlerExecutionChain if (mappedHandler == null) { noHandlerFound(processedRequest, response); return; }

    // Determine handler adapter for the current request. HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());//根据handler获取对应的HandlerAdapter

    //getHandlerAdapter源码 遍历所有的HandlerAdapter 判断是否支持当前handler,支持返回对应的HandlerAdapter protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { if (this.handlerAdapters != null) { for (HandlerAdapter ha : this.handlerAdapters) { if (logger.isTraceEnabled()) { logger.trace(“Testing handler adapter [” + ha + “]”); } if (ha.supports(handler)) { return ha; } } } throw new ServletException(“No adapter for handler [” + handler + “]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler”); }

  • 4.HandlerAdapter接口中的方法

    boolean supports(Object handler);//判断是否支持当前handler //执行handler @Nullable ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception; long getLastModified(HttpServletRequest request, Object handler);

  • 5.HandlerAdapter及其子类

  • 6.简单模拟写一下适配器模式,及其对应的controller源码

    /**

    • @author 长名06
    • @version 1.0
    • Controller接口 */ public interface Controller {

    }

    class HttpController implements Controller{ public void doHttpController(){ System.out.println(“http…”); } }

    class SimpleController implements Controller{ public void doSimpleController(){ System.out.println(“simple…”); } }

    class AnnotationController implements Controller{ public void doAnnotationController(){ System.out.println(“annotation…”); } } /** * @author 长名06 * @version 1.0 * 适配器接口 * 一个controller对应一个handlerAdapter */ public interface HandlerAdapter {

    //判断handler是否是当前适配器对应的controller
    boolean supports(Object handler);
    
    
    void handle(Object handler);
    

    }

    class HttpHandlerAdapter implements HandlerAdapter{ @Override public boolean supports(Object handler) { return (handler instanceof HttpController); }

    @Override
    public void handle(Object handler) {
        ((HttpController) handler).doHttpController();
    }
    

    }

    class SimpleHandlerAdapter implements HandlerAdapter{ @Override public boolean supports(Object handler) { return (handler instanceof SimpleController); }

    @Override
    public void handle(Object handler) {
        ((SimpleController) handler).doSimpleController();
    }
    

    }

    class AnnotationHandlerAdapter implements HandlerAdapter{ @Override public boolean supports(Object handler) { return (handler instanceof AnnotationController); }

    @Override
    public void handle(Object handler) {
        ((AnnotationController) handler).doAnnotationController();
    }
    

    } /** * @author 长名06 * @version 1.0 * 适配器模式 */ public class Dispatch {

    public static final List<HandlerAdapter> handlerAdapters = new ArrayList<HandlerAdapter>();
    
    
    public Dispatch(){
        handlerAdapters.add(new HttpHandlerAdapter());
        handlerAdapters.add(new AnnotationHandlerAdapter());
        handlerAdapters.add(new SimpleHandlerAdapter());
    }
    
    
    public void doDispatch(){
    

    // HttpController controller = new HttpController(); // SimpleController controller = new SimpleController(); AnnotationController controller = new AnnotationController(); HandlerAdapter adapter = getHandler(controller); adapter.handle(controller); }

    public HandlerAdapter getHandler(Controller controller){
        for(HandlerAdapter ha : this.handlerAdapters){
            if(ha.supports(controller)){
                return ha;
            }
        }
        return null;
    }
    
    
    public static void main(String[] args) {
        new Dispatch().doDispatch();
    }
    

    }

注意事项和细节

  • 1.三种形式,按照src以怎样的方式给到Adapter(在Adapter里的形式)命名的
  • 2.类适配器:以类给到,在Adapter里,就是将src当作类,继承;对象适配器:以对象给到 ,在Adapter里,将src作为一个对象持有;接口适配器:以接口给到,在Adapter里,将src作为一个接口,实现。
  • 3.Adapter模式最大的作用就是将原本不兼容的接口融合在一起工作。
  • 4.实际开发中,不一定非要按照这三种要求,重要的是其思想

只是为了记录自己的学习历程,且本人水平有限,不对之处,请指正。

内容
  • 修复 GitLab 的 CI Runner 提示找不到 pwsh 执行文件
    修复 GitLab 的 CI R
    2023-12-11
    本文告诉大家如何修复使用 GitLab 的 Runner 做 CI 时提示 “pwsh”: executable fil
  • RocketMQ消费者是如何负载均衡的
    RocketMQ消费者是如何负载
    2023-12-09
    摘要:RocketMQ 支持两种消息模式:集群消费( Clustering )和广播消费( Broadcasting )
  • 翻越相机标定的奥林匹斯
    翻越相机标定的奥林匹斯
    2023-12-07
    在机器视觉领域,相机标定是不可或缺的一步,而张氏标定法,因其灵活性,是各种标定方法中最有影响力的一种,称其为相机标定的
  • 解析关于Tomcat Servlet-request的获取请求参数及几种常用方法
    解析关于Tomcat Servl
    2023-12-06
    摘要: 本文主要讲解Tomcat之Servlet-request请求参数、Servlet转发机制、常用方法.本文分享自华
  • 零信任介绍
    零信任介绍
    2023-12-04
    什么是零信任?.答:.零信任是一种条件访问控制模型,需要持续进行信任验证,然后才允许对应用和数据进行最低权限访问。零信任
  • 在光线追踪中避免自相交的方法
    在光线追踪中避免自相交的方法
    2023-12-04
    这是我阅读 Ray Tracing Gem 的一篇笔记,《避免自相交的快速可靠的方法》是 Ray Tracing Gem
  • FlashDuty Changelog 2023-09-07 | 新增深色模式与主题配置
    FlashDuty Change
    2023-12-04
    FlashDuty:一站式告警响应平台,前往此地址免费体验!.FlashDuty.现在已经全面支持了深色模式,这为您提供
  • 毛衣
    毛衣
    2024-01-10
    毛衣产品介绍.产品功能.保暖:毛衣采用高品质的羊毛或羊毛混纺材料制成,具有良好的保暖性能,能有效阻挡寒冷空气对人体的侵袭
  • 短裤
    短裤
    2023-12-11
    时尚舒适,让您夏日更自在.产品功能.采用轻薄、透气的面料,给您清新舒适的穿着体验.弹性腰头设计,更贴合您的腰部曲线,穿着
  • 风衣
    风衣
    2023-12-21
    风衣.产品功能.透气性高,能够有效排出体内热量和汗液,保持身体舒适.防风防水,能够有效阻挡外界风雨,保护身体不受天气影响
  • 儿童运动服
    儿童运动服
    2023-12-16
    儿童运动服.产品功能.我们的儿童运动服采用高品质的面料和工艺制作而成,具有出色的透气性和舒适性,可以让孩子在运动中保持干
  • 男童短裤
    男童短裤
    2023-12-31
    男童短裤.产品功能.我们的男童短裤是为年轻活泼的男孩设计的。它采用了透气轻便的面料,让孩子在炎热的夏天也能感到舒适。弹性
  • 牛仔裤
    牛仔裤
    2024-01-05
    牛仔裤.牛仔裤,是一种起源于美国的经典服装单品,以其耐穿耐磨的特性,成为了时尚界不可或缺的一部分。无论是男女老少,都能在
  • 商务西服
    商务西服
    2023-12-16
    商务西服.商务西服是一款专为商务场合打造的男士正装,其独特的设计和高品质的面料使其成为商务精英们的首选。不论是参加重要的
  • 婴儿连体衣
    婴儿连体衣
    2023-12-21
    婴儿连体衣.产品描述.婴儿连体衣是专门为婴儿设计的一款便捷舒适的睡衣,它将上衣和裤子融为一体,令宝宝在睡觉及活动时更加方
  • 袜子
    袜子
    2023-12-26
    产品介绍.产品功能.我们的袜子采用了优质的天然材料,具有吸湿透气、舒适柔软的特点。特别设计的弹性帮助固定袜子位置,并且不
  • 短裤
    短裤
    2023-12-11
    时尚舒适,尽显运动魅力——短裤.产品功能.透气吸汗:采用透气材质制作,有效吸收汗液,让您在运动中保持干爽舒适。.伸缩自如