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 作为一个接口,实现。

优点:

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

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

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/939707.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

系列2:基于Centos-8.6Kubernetes 集成GPU资源信息

每日禅语 自省,就是自我反省、自我检查,自知己短,从而弥补短处、纠正过失。佛陀强调自觉觉他,强调以达到觉行圆满为修行的最高境界。要改正错误,除了虚心接受他人意见之外,还要不忘时时观照己身。自省自悟之…

leetcode17:电话号码的字母组合

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。 示例 1: 输入:digits "23" 输出&#…

OpenHarmony-3.HDF Display子系统(6)

Display 子系统 1.Display驱动模型介绍 当前操作系统和 SOC 种类繁多,各厂商的显示屏器件也各有不同,随之针对器件的驱动代码也不尽相同,往往是某一款器件驱动,只适用于某单一内核系统或 SOC,如果要迁移到其他内核或者…

AQS源码学习

一、park/unpark阻塞唤醒线程 LockSupport是JDK中用来实现线程阻塞和唤醒的工具。使用它可以在任何场合使线程阻塞,可以指定任何线程进行唤醒,并且不用担心阻塞和唤醒操作的顺序,但要注意连续多次唤醒的效果和一次唤醒是一样的。JDK并发包下…

GUI07-学工具栏,懂MVC

MVC模式,是天底下编写GUI程序最为经典、实效的一种软件架构模式。当一个人学完菜单栏、开始学习工具栏时,就是他的一生中,最适合开始认识 MVC 模式的好时机之一。这节将安排您学习: Model-View-Controller 模式如何创建工具栏以及…

C++----类与对象(中篇)

引言 以C语言栈的实现为例,在实际开发中,我们可能会遇到以下两个问题: 1.初始化和销毁管理不当:C语言中的栈实现通常需要手动管理内存(如使用malloc和free),这导致初始化和销毁栈时容易出错或…

linux打包qt程序

Linux下Qt程序打包_linuxdeployqt下载-CSDN博客 Linux/Ubuntu arm64下使用linuxdeployqt打包Qt程序_linuxdeployqt arm-CSDN博客 本篇文章的系统环境是 : 虚拟机ubuntu18.04 用下面这个qmake路径 进行编译 在 ~/.bashrc 文件末尾,qmake目录配置到文件末尾 将上图中…

气象与旅游之间的关系,如果借助高精度预测提高旅游的质量

气象与旅游之间存在密切的关系,天气条件直接影响旅游者的出行决策、旅游体验和安全保障。通过高精度气象预测技术,可以有效提升旅游质量,为游客和旅游行业带来显著的优势。 1. 提高游客出行决策效率 个性化天气服务:基于高精度气象预测,旅游平台可以提供个性化的天气预报服…

华为OD --- 靠谱的车

华为OD --- 靠谱的车 题目OJ用例独立实现思路源码 参考实现思路源码实现 题目 OJ用例 测试用例case 独立实现 思路 独立实现的思路比较简单,直接建一个长度为N的数组,然后找出index中不包含4的项数即可 源码 const rl require("readline").createInterface({ …

可视化平台FineReport的安装及简单使用

1. FineReport产品 FineReport介绍 FineReport报表软件是一款纯Java编写的、集数据展示(报表)和数据录入(表单)功能于一身的企业级web报表工具,它专业、简捷、灵活的特点和无码理念,仅需简单的拖拽操作便可以设计复杂的中国式报表,搭建数据决…

OkHttp源码分析:分发器任务调配,拦截器责任链设计,连接池socket复用

目录 一,分发器和拦截器 二,分发器处理异步请求 1.分发器处理入口 2.分发器工作流程 3.分发器中的线程池设计 三,分发器处理同步请求 四,拦截器处理请求 1.责任链设计模式 2.拦截器工作原理 3.OkHttp五大拦截器 一&#…

Nginx主要知识点总结

1下载nginx 到nginx官网nginx: download下载nginx,然后解压压缩包 然后双击nginx.exe就可以启动nginx 2启动nginx 然后在浏览器的网址处输入localhost,进入如下页面说明nginx启动成功 3了解nginx的配置文件 4熟悉nginx的基本配置和常用操作 Nginx 常…

概率论得学习和整理27:关于离散的数组 随机变量数组的均值,方差的求法3种公式,思考和细节。

目录 1 例子1:最典型的,最简单的数组的均值,方差的求法 2 例子1的问题:例子1只是1个特例,而不是普遍情况。 2.1 例子1各种默认假设,导致了求均值和方差的特殊性,特别简单。 2.2 我觉得 加权…

初学stm32 --- 时钟配置

目录 stm32时钟系统 时钟源 (1) 2 个外部时钟源: (2)2 个内部时钟源: 锁相环 PLL PLLXTPRE: HSE 分频器作为 PLL 输入 (HSE divider for PLL entry) PLLSRC: PLL 输入时钟源 (PL…

Latex+VsCode+Win10搭建

最近在写论文,overleaf的免费使用次数受限,因此需要使用本地的形式进行编译。 安装TEXLive 下载地址:https://mirror-hk.koddos.net/CTAN/systems/texlive/Images/ 下载完成直接点击iso进行安装操作。 安装LATEX Workshop插件 设置VsCode文…

深度学习之目标检测篇——残差网络与FPN结合

特征金字塔多尺度融合特征金字塔的网络原理 这里是基于resnet网络与Fpn做的结合,主要把resnet中的特征层利用FPN的思想一起结合,实现resnet_fpn。增强目标检测backone的有效性。代码实现如下: import torch from torch import Tensor from c…

Leetcode 面试150题 399.除法求值

系列博客目录 文章目录 系列博客目录题目思路代码 题目 链接 思路 广度优先搜索 我们可以将整个问题建模成一张图:给定图中的一些点(点即变量),以及某些边的权值(权值即两个变量的比值),试…

python实现Excel转图片

目录 使用spire.xls库 使用excel2img库 使用spire.xls库 安装:pip install spire.xls -i https://pypi.tuna.tsinghua.edu.cn/simple 支持选择行和列截图,不好的一点就是商业库,转出来的图片有水印。 from spire.xls import Workbookdef …

hpe服务器更新阵列卡firmware

背景 操作系统:RHEL7.8 hpe服务器经常出现硬盘断开,阵列卡重启问题,导致系统hang住。只能手动硬重启。 I/O error,dev sda smartpqi 0000:5c:00:0: resettiong scsi 1:1:0:1 smartpqi 0000:5c:00:0: reset of scsi 1:1:0:1:…

excel 使用vlook up找出两列中不同的内容

当使用 VLOOKUP 函数时,您可以将其用于比较两列的内容。假设您要比较 A 列和 B 列的内容,并将结果显示在 C 列,您可以在 C1 单元格中输入以下公式: 这个公式将在 B 列中的每个单元格中查找是否存在于 A 列中。如果在 A 列中找不到…