zoukankan      html  css  js  c++  java
  • 【设计模式】第六篇:来康康适配器模式

    一 引言

    设计模式就是一种思想,一种设计方式,他可以帮助我们对于一些问题(不一定是技术,如生活中的问题)的处理提供一些思路,以及问题解决方案的建模与描述

    例如我们今天要讲的适配器模式就是从解决生活问题,过渡到了技术层面的问题

    现实生活中,常常会出现两者不能兼容的一种情况,例如出国了,我们从国内带的充电插头与外国的插孔就不匹配,再例如我去香港旅游,但是又不会讲粤语,在一些小一些的商店买东西,就需要一个会讲粤语的朋友帮我在中间翻译

    换到技术层面中,我们开发某些业务的部分组件已经在库中存在了,但是由于过去开发组件时与当前接口规范不兼容,使用适配器模式,也就是找一个中间量,帮助我们适配两者,对接起来,这样就不用再开发一个新的组件了

    二 代码演示

    例子背景是这样的,我们现在有一台苹果手机(Lightning 接口),但是我们现在只有一根 Type-C 的充电线,我们需要想办法,增加一个中间的转接器,从而能达到给手机充电的效果

    (一) 类适配器(继承,不常用)

    (1) 演示

    虽然这一种不常用,但是第二种就是在第一种基础上改进的,内容不是很多,可以耐心看完喔

    首先,定义一个苹果手机类,其中有一个充电的方法(Converter 在后面有说,接着往下看)

    /**
     * 客户端类:苹果手机想充电,但是充电线的头是 Type-C 的
     */
    public class Phone {
        // 充电方法
        public void charging(Converter converter){
            converter.TypeCToLightning();
        }
    }
    

    接着定义的就是 Type-C 这条充电线,因为它是没办法插入苹果手机的 Lightning 接口 的,所以它就是被适配的类

    /**
     * 被适配的类:Type-C充电线
     */
    public class TypeCLine {
    
        public void charging(){
            System.out.println("开始充电了");
        }
    }
    

    两个不能直接联系的内容,我们已经定义好了,即手机和 Type-C 充电线,现在就差一个中间的适配器了,现在可以定义一个转换的接口,其中定义一个Type-C 转为 Lightning 的方法

    /**
     * 充电器转换接口
     */
    public interface Converter {
        // Type-C 转为 苹果 Lightning 接口
        void TypeCToLightning();
    }
    

    接下来就是一个具体的实现类了,实现抽象接口没什么好说的,还有一步是关键——继承充电线这个需要被适配的类,至于它的利弊我们下面再说

    /**
     * Type-C 充电线转化器
     */
    public class TypeCLineAdapter extends TypeCLine implements Converter {
        @Override
        public void TypeCToLightning() {
            // 转接成功,可以使用经过转接后的 type-C 的线充苹果手机了
            super.charging(); 
        }
    }
    

    测试一下

    public class Test {
        public static void main(String[] args) {
            Phone phone = new Phone(); // 手机
            TypeCLine typeCLine = new TypeCLine(); // Type-C充电线
            Converter typeCLineAdapter = new TypeCLineAdapter(); // Type-C充电线转接器
            // 手机直接引入转接器从而充电
            phone.charging(typeCLineAdapter);
        }
    }
    

    结果:开始充电了

    (2) 利弊

    测试代码中,大家应该也能看出来了 typeCLine 好像并没有被用到,确实如此,因为我们在适配器类,即 TypeCLineAdapter 类中,是通过直接继承 TypeCLine 这个 Type-C 充电线类的,也就是说,它的理念是通过多重继承来实现两个接口之间进行匹配,但是像 C#,VB.NET,Java等语言都是不支持多继承的,而且其使用了继承,继承在控制不恰当的情况下总会给我们带来一些麻烦,所以在这里也并不是很合适,所以就有了下面的方式

    (二) 对象适配器(组合,常用)

    (1) 演示

    手机和 Type-C 充电线这是不变的,需要做的就是修改具体的适配器类 TypeCLineAdapter,我们这里创建一个新的 TypeCLineAdapter2

    /**
     * Type-C 充电线转化器
     */
    public class TypeCLineAdapter2 implements Converter {
    
        private TypeCLine typeCLine;
    
        public TypeCLineAdapter2(TypeCLine typeCLine) {
            this.typeCLine = typeCLine;
        }
    
        @Override
        public void TypeCToLightning() {
            // 转接成功,可以使用经过转接后的 type-C 的线充苹果手机了
            typeCLine.charging(); 
        }
    }
    

    测试一下:

    public class Test {
        public static void main(String[] args) {
            Phone phone = new Phone(); // 手机
            TypeCLine typeCLine = new TypeCLine(); // Type-C充电线
            Converter typeCLineAdapter2 = new TypeCLineAdapter2(typeCLine); // Type-C充电线转接器
            // 手机直接引入转接器从而充电
            phone.charging(typeCLineAdapter2);
        }
    }
    

    (2) 利弊

    在 TypeCLineAdapter2 的步骤中,首先我们取消了适配器继承 TypeCLine 类,而是选择通过在适配器TypeCLineAdapter2 这个类 中增加一个 TypeCLine 的私有域,然后再在方法中调用

    首先,我们摆脱了单继承带来的烦恼,那么这样做还有什么好处吗

    在 《Effecttive Java》一书中,第 4 章 第 18 条:复合优先于继承中有提到,有一个比较好的说法,我简单摘了一下:

    我们可以创建一个新的类(适配器 TypeCLineAdapter2 类),在新的类中添加一个私有域(TypeCLine 类),他引用现有类的一个实例,这种设计叫做复合

    • 因此现有的类变成了新类的一个组件,新类中的每个实例方法都可以调用被包含的现有的类中对应的方法,并返回他的结果,这就是转发,而新类中的方法被称为 转发方法

    小结:这种方式下,测试的时候感觉也会更舒服,和我们想的一般,手机和 Type-C 的线,分别通过链接适配器,就达到了能适配充电的方式,同样又避免了使用继承,算是一种比较好的适配问题处理方式

    三 适配器模式理论

    (一) 定义和分类

    适配器模式(Adapter)定义:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作

    分类:

    • 类适配器模式

      • 主要使用继承实现,耦合度高,且在单继承的语言中使用会受限,还需要防止继承带来的一些问题
    • 对象适配器模式

      • 使用了组合(或叫复合)的方式降低了耦合,推荐使用

    (二) 结构

    ① 类适配器模式

    ② 对象适配器模式

    还是依旧分析一下其中的角色:

    适配者(Adaptee)类:它是需要被适配的类,例如上面提到的 Type-C 线,适配后才能插入到苹果手机中充电

    目标(Target)接口:当前系统业务所期待的接口,它可以是抽象类或接口,对应代码中的 Converter 接口,他是客户期待的适配转换接口

    适配器(Adapter)类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者

  • 相关阅读:
    数据库的范式
    数据库的事务
    cookie和session以及区别
    Java交换排序:冒泡排序和快速排序
    Java面向对象中:方法重载和方法重写以及区别、 this关键字和super关键字以及区别
    电子设备产品可靠性测试
    软件测试思考笔记(The beauty of software testing)
    常见软件系统架构解决方案
    常见计算机系统架构
    性能测试
  • 原文地址:https://www.cnblogs.com/ideal-20/p/13977209.html
Copyright © 2011-2022 走看看