• Java设计模式-结构型模式-适配器模式


    适配器模式

    在这里插入图片描述
    如图:国外插座标准和国内不同,要使用国内的充电器,就需要转接插头,转接插头就是起到适配器的作用

    适配器模式,是将某个类的接口转化为客户端期望的另一个接口表示,主要的目的是解决兼容性问题,让原本不匹配不能一起工作的两个类可以协同工作

    应用场景

    1. 集成旧系统:当引入新系统时,通常需要与现有的旧系统进行集成。适配器模式可以帮助将新系统的接口适配成旧系统所期望的接口,从而实现两个系统之间的兼容性。例如,将新的支付系统接口适配成与旧的支付系统兼容的接口。

    2. 类库适配:当使用第三方类库时,有时需要将其接口适配成符合自己项目需求的接口。适配器模式可以用来封装第三方类库的接口,使其与项目代码无缝集成。例如,将不同数据库操作类库的接口适配成统一的数据库操作接口。

    3. 跨平台兼容:在跨平台开发中,不同平台可能有不同的接口和实现方式。适配器模式可以帮助将不同平台的接口适配成统一的接口,从而提供跨平台的兼容性。例如,将移动应用在不同操作系统上的界面适配成统一的用户界面。

    4. 日志记录器:在应用中使用不同的日志记录库时,可以使用适配器模式将它们的接口适配成统一的接口,以便在应用中无缝切换不同的日志记录库。

    5. 第三方API集成:当与第三方API进行集成时,可能需要将第三方API的接口适配成符合自己应用的接口规范。适配器模式可以帮助实现与第三方API的集成,并提供统一的接口给应用程序使用。

    适配器模式有三种实现方式:类适配器模式、对象适配器模式、接口适配器模式

    案例

    已知家用电是220V的交流电,类如下,可以提供220V的电压

    public class HouseholdElectricity220V {
        /**
         * 输出220V电压
         * @return
         */
        public int output220V(){
            return 220;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    而我的手机需要使用5V的直流电,设立目标接口

    public interface MobileElectricity {
        int output5V();
    
        int output10V();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    我的需求是:我要给手机充电!
    那么有两条路可以选择:

    1. 我去和供电站商量,开一条5V直流电的通路,我直接连上充电
    2. 我开发一个适配器,把220V电压转为手机需要的5V直流电
      很明显,只能使用方法2,开发一个适配器。
      通过上述案例,应该可以体会到什么场景下需要使用适配器模式了
    3. 原始接口复杂且稳定,且与新需求有关联。可以通过适配器模式简化开发
    4. 新的需求需要兼容老的需求
      不废话了
      下面分别使用 类适配器模式、对象适配器模式、接口适配器模式 实现该电源适配器

    类适配器模式

    类适配器模式就是 通过继承 被适配者类 ,来实现适配器兼容
    适配器实现如下:

    public class MobileAdapter5VClass extends HouseholdElectricity220V implements MobileElectricity{
        @Override
        public int output5V() {
            super.output220V();
            /*变压操作*/
            System.out.println("开始变压220V->5V");
            System.out.println("输出5V");
            return 5;
        }
    
        @Override
        public int output10V() {
            super.output220V();
            /*变压操作*/
            System.out.println("开始变压220V->10V");
            System.out.println("输出10V");
            return 10;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    通过继承 被适配的 类,将被适配类和目标接口关联起来
    测试代码如下:

    /**
     * 类适配器模式
     */
    @Test
    public void adapterClassTest(){
        MobileAdapter5VClass adapter = new MobileAdapter5VClass();
        adapter.output5V();
    }
    输出:
    输出220V电压
    开始变压220V->5V
    输出5V
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    因为依赖类的继承来实现,自然耦合性较高,违反了合成复用原则(尽量多使用组合、聚合,少使用继承)

    想要降低耦合性,就要使用组合的方式,实现适配器,即:对象适配器模式

    对象适配器模式

    通过聚合 被适配的类 来实现 适配器
    直接看代码:

    public class MobileAdapter5VObject implements MobileElectricity{
    
        private final HouseholdElectricity220V electricity220V;
    
        public MobileAdapter5VObject(HouseholdElectricity220V householdElectricity220V) {
            this.electricity220V = householdElectricity220V;
        }
    
        @Override
        public int output5V() {
            electricity220V.output220V();
            /*变压操作*/
            System.out.println("开始变压220V->5V");
            System.out.println("输出5V");
            return 5;
        }
    
        @Override
        public int output10V() {
            electricity220V.output220V();
            /*变压操作*/
            System.out.println("开始变压220V->10V");
            System.out.println("输出10V");
            return 10;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    /**
     * 对象适配器模式
     */
    @Test
    public void adapterObjectTest(){
        HouseholdElectricity220V electricity220V = new HouseholdElectricity220V();
        MobileAdapter5VObject adapter = new MobileAdapter5VObject(electricity220V);
        adapter.output5V();
    }
    输出:
    输出220V电压
    开始变压220V->5V
    输出5V
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    看到这里,大家应该发现一个问题,我的目标接口有两个方法,output5V() 和 output10V()
    而 output5V() 才是我本次需求所需要的,但是因为接口的限制,在实现适配器的时候,又不得不重写
    output10V() 方法。这样的代码一点也不优雅,而且封装性不好。
    有什么解决办法呢?
    想一想,上一步我们把被适配 类 和 适配器类进行了解耦,那么能不能把 目标接口 和适配器也解耦呢
    所以 就有了 接口适配器模式
    可以使用抽象类 先继承 目标接口,并重写接口方法为空方法。适配器只和抽象类交互,只实现自己需要的方法。

    接口适配器模式

    接口的适配器是这样的:接口中往往有多个抽象方法,但是我们写该接口的实现类的时候,必须实现所有这些方法,这明显有时比较浪费,因为并不是所有的方法都是我们需要的,有时只需要某一些.

    当不希望实现一个接口中所有的方法时,可以创建一个抽象类Adapter ,实现所有方法。而此时我们只需要继承该抽象类即可
    直接看代码:

    /**
    *	抽象适配器类
    */
    public abstract class AbsMobileAdapter implements MobileElectricity{
        @Override
        public int output5V() {
            throw new RuntimeException("请先重写");
        }
    
        @Override
        public int output10V() {
            throw new RuntimeException("请先重写");
        }
    }
    
    /*********************************************************************************/
    /**
     * 接口适配器类
     **/
    public class MobileAdapter5VInterface extends AbsMobileAdapter{
        private final HouseholdElectricity220V electricity220V;
    
        public MobileAdapter5VInterface(HouseholdElectricity220V electricity220V) {
            this.electricity220V = electricity220V;
        }
    
        @Override
        public int output5V() {
            electricity220V.output220V();
            /*变压操作*/
            System.out.println("开始变压220V->5V");
            System.out.println("输出5V");
            return 5;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    适配器模式在源码中的使用

    1. JDBC驱动程序:不同的数据库提供商实现了不同的JDBC驱动接口,使用适配器模式可以将这些不同的接口适配为标准的JDBC接口,提高应用程序的可移植性。
    2. 日志框架:Java中有多个常用的日志框架,如Log4j、SLF4J等,不同的日志框架提供的API不同,使用适配器模式可以将这些不同的API适配为一个统一的接口,方便再程序中进行日志记录和管理。
    3. 第三方库或SDK:在使用第三方库或 SDK 时,可能由于它们实现的 API 不同而导致应用程序复杂,使用适配器模式可以将不同的 API 适配为统一的接口,简化应用程序的调用。
  • 相关阅读:
    Apollo星火计划学习笔记第五讲——Apollo感知模块详解实践1
    react生命周期钩子函数
    《C和指针》笔记34:字符串函数
    CTreeCtrl自绘
    设计模式:状态模式(C++实现)
    C语言-指针详解速成
    计算机毕业设计 高校普法系统的设计与实现 Java实战项目 附源码+文档+视频讲解
    Windows10/11显示文件扩展名 修改文件后缀名教程
    数据结构学习笔记——线索二叉树
    Java设计模式面试题和答案
  • 原文地址:https://blog.csdn.net/ren9436/article/details/134429641