zoukankan      html  css  js  c++  java
  • java设计模式——适配器模式

    一. 定义与类型

    定义:将一个类的接口转换成客户期望的另一个接口,使原本不兼容的类可以一起工作

    类型:结构性

    二. 使用场景

    (1) 已经存在的类,它的方法和需求不匹配时(方法结果相同或相似)

    (2) 不是软件设计阶段考虑的设计模式,是随着软件维护,由于不同产品,不同厂家造成功能类似而接口不相同情况下的解决方案

    三. 优缺点

    优点:

      (1) 能提高类的透明性和复用,现有的类复用但不需要改变

      (2) 目标类和适配器类解耦,提高程序扩展性

      (3) 符合开闭原则

    缺点:

      (1) 适配器编写过程需要全面考虑,可能会增加系统的复杂新

      (2) 增加系统代码可读的难度

    四. 适配器—扩展

    对象适配器:通过组合,优先先择组合

    类适配器:通过继承

    五. 相关设计模式

    适配器模式和外观模式:

    (1) 它们都是对现有的类,现存的系统封装。

    (2) 适配器是使用已有的接口,让两个或多个已有的接口协同工作,外观模式定义新的接口,在现有系统中提供一个更为方便的访问入口。

    (3) 如果非要把外观模式也称之为适配,那它们最大的区别就是适配的力度不同。外观模式是适配整个子系统,所针对的对象力度更大。

    六. Coding

    类适配器:

    替换目标方法的适配的方法

    /**
     * @program: designModel
     * @description:
     * @author: YuKai Fan
     * @create: 2019-02-11 16:01
     **/
    public class Adaptee {
        public void AdapteeRequest() {
            System.out.println("被适配者的方法");
        }
    }

    目标接口:

    /**
     * @program: designModel
     * @description:
     * @author: YuKai Fan
     * @create: 2019-02-11 16:02
     **/
    public interface Target {
        void request();
    }

    目标方法:

    /**
     * @program: designModel
     * @description:
     * @author: YuKai Fan
     * @create: 2019-02-11 16:03
     **/
    public class ConcreteTarget implements Target {
        public void request() {
            System.out.println("ConcreteTarget目标方法");
        }
    }

    适配方法:

    /**
     * @program: designModel
     * @description:
     * @author: YuKai Fan
     * @create: 2019-02-11 16:03
     **/
    public class Adapter extends Adaptee implements Target {
        public void request() {
            //...可以加上逻辑
            super.AdapteeRequest();
            //...可以加上逻辑
        }
    }

    应用层:

    /**
     * @program: designModel
     * @description:
     * @author: YuKai Fan
     * @create: 2019-02-11 16:05
     **/
    public class Test {
        public static void main(String[] args) {
            Target target = new ConcreteTarget();
            target.request();
            Target adapterTarget = new Adapter();
            adapterTarget.request();
        }
    }

    结果:

    对象适配器:

    /**
     * @program: designModel
     * @description:
     * @author: YuKai Fan
     * @create: 2019-02-11 16:07
     **/
    public class Adaptee {
        public void AdapteeRequest() {
            System.out.println("被适配者的方法");
        }
    }
    /**
     * @program: designModel
     * @description:
     * @author: YuKai Fan
     * @create: 2019-02-11 16:02
     **/
    public interface Target {
        void request();
    }
    /**
     * @program: designModel
     * @description:
     * @author: YuKai Fan
     * @create: 2019-02-11 16:03
     **/
    public class ConcreteTarget implements Target {
        public void request() {
            System.out.println("ConcreteTarget目标方法");
        }
    }
    /**
     * @program: designModel
     * @description: 通过组合的方式,把具体实现request的方法委托给Adaptee来实现
     * @author: YuKai Fan
     * @create: 2019-02-11 16:03
     **/
    public class Adapter implements Target {
        private Adaptee adaptee = new Adaptee();
        public void request() {
            //...
            adaptee.AdapteeRequest();
            //...
        }
    }
    /**
     * @program: designModel
     * @description:
     * @author: YuKai Fan
     * @create: 2019-02-11 16:05
     **/
    public class Test {
        public static void main(String[] args) {
            Target target = new ConcreteTarget();
            target.request();
    
            Target adapterTarget = new Adapter();
            adapterTarget.request();
        }
    }

    从上面的代码可以看出,类适配器与对象适配器主要是在适配的过程,类适配器是通过继承,而对象适配器是通过组合。

    用一个业务场景来体现对象适配器模式,

     adaptee被适配的方法:

    /**
     * @program: designModel
     * @description: 220v的交流电
     * @author: YuKai Fan
     * @create: 2019-02-11 16:13
     **/
    public class AC220 {
        public int outputAC220V() {
            int output = 220;
            System.out.println("输出交流电" + output + "V");
            return output;
        }
    }

     目标方法的接口:

    /**
     * @program: designModel
     * @description: 目标:5v直流电
     * @author: YuKai Fan
     * @create: 2019-02-11 16:16
     **/
    public interface DC5 {
        int outputDC5V();
    }

    适配方法,将220v交流电,适配为5v直流电:

    /**
     * @program: designModel
     * @description:
     * @author: YuKai Fan
     * @create: 2019-02-11 16:17
     **/
    public class PowerAdapter implements DC5 {
        private AC220 ac220 = new AC220();
    
        public int outputDC5V() {
            int adapterInput = ac220.outputAC220V();
    
            //变压器...
            int adapterOutput = adapterInput/44;
    
            System.out.println("使用PowerAdapter输入AC:" + adapterInput + "V" + ",输出DC:" + adapterOutput);
            return adapterOutput;
        }
    }

     应用层:

    /**
     * @program: designModel
     * @description:
     * @author: YuKai Fan
     * @create: 2019-02-11 16:19
     **/
    public class Test {
        public static void main(String[] args) {
            DC5 dc5 = new PowerAdapter();
            dc5.outputDC5V();
        }
    }

     结果:

    UML类图:

    七. 源码分析

    jdk中的xmlAdapter

    Spring AOP中的AdvisorAdapter的实现方法

    Spring-data-jpa中的JpaVendorAdapter的相关实现类

    SpringMVC中的HandlerAdapter的相关实现,

    SpringMVC的核心控制器DispatcherServlet

  • 相关阅读:
    JAVA多态
    JAVA中的继承
    Nginx配置中root和alisa指定文件路径的区别
    NGINX配置详解
    Jenkins填坑之邮件模板分享
    jenkins填坑之HTML报告样式问题
    Jenkins填坑之仅获取本次构建的HTML报告作为附件发送邮件
    Jenkins填坑之发送邮件无法获取HTML报告作为附件
    jenkins填坑之邮件模板中的变量无法正常获取值
    Jenkins填坑之构建ant项目时,执行结果提示input file xxx.jtl does not exist
  • 原文地址:https://www.cnblogs.com/FanJava/p/10362565.html
Copyright © 2011-2022 走看看