当前位置: 首页 > article >正文

Java设计模式 —— 【结构型模式】适配器模式(类的适配器、对象适配器、接口适配器)详解

文章目录

  • 基本介绍
  • 一、类的适配器
  • 二、对象适配器
  • 三、接口适配器
  • 总结


基本介绍

生活中有很多例子:

  • 不同国家的插座接口不同,需要转换器;
  • 家用电源220V,手机只接受5V充电,需要转换器;
  • 读卡器,拓展坞。。。

在这里插入图片描述
定义:

​ 适配器模式的主要作用是将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。

​ 适配器模式分为类适配器模式和对象适配器模式,前者类之间的耦合度比后者高,且要求程序员了解现有组件库中的相关组件的内部结构,所以应用相对较少些。

结构:

适配器模式(Adapter)包含以下主要角色:

  • 目标(Target)接口: 当前系统业务所期待的接口,它可以是抽象类或接口;
  • 适配者(Adaptee)类: 它是被访问和适配的现存组件库中的组件接口;
  • 适配器(Adapter)类: 它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。

一、类的适配器

实现方式:定义一个适配器类来实现当前系统的业务接口,同时又继承现有组件库中已经存在的组件。

【例】手机充电器

家用电源220V,手机只接受5V充电,要想给手机充电,我们得需要一个转换器。

在这里插入图片描述
家用电源【适配者类】:

public class Voltage220V {
    public Integer output22V() {
        return 220;
    }
}

目标接口:

//充电器接口
public interface IVoltage5V {
    Integer output5V();
}

//给个实现类
public class Voltage5V implements IVoltage5V {

    @Override
    public Integer output5V() {
        return 5;
    }
}

适配器类:

public class VoltageAdapter extends Voltage220V implements IVoltage5V {

    @Override
    public Integer output5V() {
        return 5;
    }
}

手机类:

public class Phone {
    public void charging(IVoltage5V iVoltage5V) {
        if(iVoltage5V.output5V() == 5) {
            System.out.println("电压5V, 正在充电。。。");
        } else {
            System.out.println("只能使用5V电压充电。。。");
        }
    }
}

测试:

public class Client {
    public static void main(String[] args) {
        Phone phone = new Phone();
        System.out.println("===直接使用5V电源充电===");
        phone.charging(new Voltage5V());
        System.out.println("===使用类适配器充电===");
        phone.charging(new VoltageAdapter());
    }
}

在这里插入图片描述
小结:

  1. Java 是单继承机制,所以类适配器需要继承src一个缺点,因为这要求dst必须是接口,有一定局限性;
  2. src类的方法在 Adapter 中都会暴露出来,也增加了使用的成本;
  3. 由于其继承了 src 类,所以它可以根据需求重写 src 类的方法,使得 Adapter 的灵活性增强了。

二、对象适配器

  1. 对象适配器模式可釆用将现有组件库中已经实现的组件引入适配器类中,该类同时实现当前系统的业务接口;
  2. 基本思路和类的适配器模式相同,只是将 Adapter 类作修改,不是继承 src 类,而是持有 src 类的实例,以解兼容性的问题。 即:持有 src 类,实现 dst 类接口,完成 src -> dst 的适配;
  3. 根据“合成复用原则”,在系统中尽量使用关联关系(聚合)来替代继承关系;
  4. 对象适配器模式是适配器模式常用的一种。

使用对象适配器将上述案例做以修改后,UML类图为:

在这里插入图片描述
家用电源【适配者类】:

public class Voltage220V {
    public Integer output220V() {
        return 220;
    }
}

目标接口:

public interface IVoltage5V {
    Integer output5V();
}

public class Voltage5V implements IVoltage5V {

    @Override
    public Integer output5V() {
        return 5;
    }
}

适配器类:

public class VoltageAdapter implements IVoltage5V {
    private Voltage220V voltage220V;

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

    @Override
    public Integer output5V() {
        //适配规则
        Integer v220 = voltage220V.output220V();
        return v220 / 44;
    }
}
public class Phone {
    public void charging(IVoltage5V iVoltage5V) {
        System.out.println("正在充电, 电压" + iVoltage5V.output5V() + "V");
    }
}

测试:

public class Demo2 {
    public static void main(String[] args) {
        Phone phone = new Phone();
        System.out.println("===直接使用5V电源充电===");
        phone.charging(new Voltage5V());
        System.out.println("===使用对象适配器充电===");
        phone.charging(new VoltageAdapter(new Voltage220V()));
    }
}

在这里插入图片描述

  1. 对象适配器和类适配器其实算是同一种思想,只不过实现方式不同。根据合成复用原则,使用组合替代继承,所以它解决了类适配器必须继承src的局限性问题,也不再要求 dst必须是接口;
  2. 使用成本更低,更灵活。

三、接口适配器

  1. 适配器又叫缺省适配器模式;
  2. 核心思路:当不需要全部实现接口提供的方法时,可先设计一个抽象类实现接口,并为该接口中每个方法提供一个默认实现(空方法),那么该抽象类的子类可有选择地覆盖父类的某些方法来实现需求;
  3. 适用于一个接口不想使用其所有的方法的情况。
    在这里插入图片描述

总结

结构:

  • 类适配器:以类给到适配器,在 Adapter 里,就是将 src 当做类,继承;
  • 对象适配器:以对象给到适配器,在 Adapter 里,将 src 作为一个对象,持有;
  • 接口适配器:以接口给到适配器,在 Adapter 里,将 src 作为一个接口,实现。

优点:

  • 适配器模式最大的作用还是将原本不兼容的接口融合在一起工作;

  • 将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,无须修改原有结构;

  • 增加了类的透明性和复用性,将具体的业务实现过程封装在适配者类中,对于客户端类而言是透明的,而且提高了适配者的复用性,同一个适配者类可以在多个不同的系统中复用;

  • 灵活性和扩展性都非常好,通过使用配置文件,可以很方便地更换适配器,也可以在不修改原有代码的基础上增加新的适配器类,完全符合“开闭原则”;

  • 对象适配器避免了但继承的缺点,可以把多个不同的适配者适配到同一个目标。


http://www.kler.cn/a/444353.html

相关文章:

  • UDP系统控制器_音量控制、电脑关机、文件打开、PPT演示、任务栏自动隐藏
  • go-zero负载均衡实现原理
  • RFdiffusion Sampler类 sample_step 方法解读
  • linux-----网络编程
  • 提炼关键词的力量:AI驱动下的SEO优化策略
  • 【返璞归真】score检验:似然比的得分检验(Likelihood Ratio Score Test)
  • 可视化平台FineReport的安装及简单使用
  • Windows 配置 Tomcat环境
  • 专业125+总分400+南京理工大学818考研经验南理工电子信息与通信工程,真题,大纲,参考书。
  • Python中map函数返回值类型用法介绍
  • arcgisPro将面要素转成CAD多段线
  • K8s HPA的常用功能介绍
  • 利用系统自带的存储感知功能清理系统中的升级补丁
  • Linux 定时任务操作详解及python简单的任务管理器
  • 设计模式-读书笔记2
  • Docker+Redis单机和集群部署【非常详细】
  • Android 获取屏幕物理尺寸
  • 建站技术 | HUGO + GitHub 创建博客页面
  • 若依前端挂Nginx、打包部署运行!!!!
  • C# 项目无法加载 DLL“SQLite.Interop.DLL”: 找不到指定的模块
  • Leetcode 409. Longest Palindrome
  • BERT模型入门(1)BERT的基本概念
  • 条件随机场(CRF)详解:原理、算法与实现(深入浅出)
  • 【软件工程】简答题系列(山东大学·软院考试专属)
  • pytest接口关联框架封装
  • 将三个list往一个excel表的三个sheet中写入,能用多线程提高写入速度