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

适配器模式

  • 适配器模式
    • 应用场景
    • 案例
    • 类适配器模式
    • 对象适配器模式
    • 接口适配器模式
    • 适配器模式在源码中的使用

适配器模式

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

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

应用场景

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

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

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

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

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

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

案例

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

public class HouseholdElectricity220V {
    /**
     * 输出220V电压
     * @return
     */
    public int output220V(){
        return 220;
    }
}

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

public interface MobileElectricity {
    int output5V();

    int output10V();
}

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

  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;
    }
}

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

/**
 * 类适配器模式
 */
@Test
public void adapterClassTest(){
    MobileAdapter5VClass adapter = new MobileAdapter5VClass();
    adapter.output5V();
}
输出:
输出220V电压
开始变压220V->5V
输出5V

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

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

对象适配器模式

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

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;
    }
}
/**
 * 对象适配器模式
 */
@Test
public void adapterObjectTest(){
    HouseholdElectricity220V electricity220V = new HouseholdElectricity220V();
    MobileAdapter5VObject adapter = new MobileAdapter5VObject(electricity220V);
    adapter.output5V();
}
输出:
输出220V电压
开始变压220V->5V
输出5V

看到这里,大家应该发现一个问题,我的目标接口有两个方法,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. JDBC驱动程序:不同的数据库提供商实现了不同的JDBC驱动接口,使用适配器模式可以将这些不同的接口适配为标准的JDBC接口,提高应用程序的可移植性。
  2. 日志框架:Java中有多个常用的日志框架,如Log4j、SLF4J等,不同的日志框架提供的API不同,使用适配器模式可以将这些不同的API适配为一个统一的接口,方便再程序中进行日志记录和管理。
  3. 第三方库或SDK:在使用第三方库或 SDK 时,可能由于它们实现的 API 不同而导致应用程序复杂,使用适配器模式可以将不同的 API 适配为统一的接口,简化应用程序的调用。

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

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

相关文章

unity使用vs进行c#代码提示,查看F12unity元代码

unity关联vs 在vs中让cs.meta显示,鼠标右键,包含在内 提示GameObject类了 感谢下面这位的提示https://zhuanlan.zhihu.com/p/551119106

esp-01刷固件/下载软件到内部单片机的方法

此文章为转载,非原创 一、准备 需要准备三个东西: 1.esp模块。ESP-01 和 ESP-01s 的引脚及 flash 容量基本完全兼容,只是内部硬件设计粗糙与否的区别,所以理论上都适用。 2.官方固件。此部分可以从安信可官方教程中下载&#xff0…

腾讯待办停止运营怎么办?导出的ics文件数据怎么打开查看

待办提醒类工具是日常办公及生活中必不可少的工具,使用待办提醒类工具可以记录很多容易忘记的事情,其可以帮助大家轻松管理各项事务和提高办事的效率。而随着工作的不断变动,大家选择待办提醒类工具也会不断的发生改变。 比如就拿我自己的使…

【算法总结】归并排序专题(刷题有感)

思考 一定要注意归并排序的含义,思考归并的意义。 主要分为两个步骤: 拆分 每次对半分(mid l r >> 1)输入:raw整块,输出:raw左块 raw右块 合并 每次都要对raw左块、 raw右块按照某种规则进行合并输入&#xf…

2023.11.15-hivesql之炸裂函数explode练习

把一个容器的多个数据炸裂出单独展示: explode(容器) 需求:将NBA总冠军球队数据使用explode进行拆分&#xff0c;并且根据夺冠年份进行倒序排序。 1.建表 --step1:建表 create table the_nba_championship(team_name string,champion_year array<string> ) row format…

Minio安装

环境 centos8&#xff0c;关闭防火墙 minio-20231101183725版本 参考官网&#xff1a;部署 MinIO&#xff1a;单节点单硬盘 — 适用于 Linux 的 MinIO 对象存储 单例 下载rpm&#xff0c;用中国镜像 wget https://dl.minio.org.cn/server/minio/release/linux-amd64/arch…

C语言判断水仙花数(ZZULIOJ1027:判断水仙花数)

题目描述 春天是鲜花的季节&#xff0c;水仙花就是其中最迷人的代表&#xff0c;数学上有个水仙花数&#xff0c;他是这样定义的&#xff1a;“水仙花数”是指一个三位数&#xff0c;它的各位数字的立方和等于其本身&#xff0c;比如153135333。 现在要求输入一个三位数&#…

数据分析 - 分散性与变异的量度

全距 - 极差 处理变异性 方差度量 数值与均值的距离&#xff0c;也就是数据的差异性 标准差描述&#xff1a;典型值 和 均值的距离的方法&#xff0c;数据与均值的分散情况

windows 安装 Oracle Database 19c

目录 什么是 Oracle 数据库 下载 Oracle 数据库 解压文件 运行安装程序 测试连接 什么是 Oracle 数据库 Oracle数据库是由美国Oracle Corporation&#xff08;甲骨文公司&#xff09;开发和提供的一种关系型数据库管理系统&#xff0c;它是一种强大的关系型数据库管理系统…

用这个平台制作电子杂志,,还能实时分享,太方便啦!

在我们看电子杂志的时候&#xff0c;总会觉得图文效果有点枯燥&#xff0c;如果能做出翻页书效果的电子杂志&#xff0c;还给人一种身临其境的真实翻书感就好了。 其实制作这种翻页电子杂志很简单&#xff0c;不需要下载安装任何软件&#xff0c;只需登录FLBOOK这个平台 &…

OCR文字识别标注小助手

目录 背景 工具界面 操作 1、选择目录 2、更改为正确的信息 3、保存 4、说明 项目 代码 下载 背景 为什么要写这么一个小工具呢&#xff1f;因为要对文字进行标注。 为什么对文字进行标注呢&#xff1f;因为要重新训练识别。 为什么要重新训练识别呢&#xff1f;因…

Linux 小程序-进度条

1.进度条准备知识 1.1回车与换行 以前的键盘会有一个这样的按键 &#xff0c;这个键就是回车与换行。 回车&#xff1a;从当前行回退到当前行的起始位置。 换行&#xff1a;从当前行切换到下一行的该位置。 有了以上的认识我们可以写出一个简单的倒计时代码&#xff1a; 注意&a…

【华为HCIP | 华为数通工程师】IPV4与IPV6 高频题(2)

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大三在校生&#xff0c;喜欢AI编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;落798. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc;️…

机器学习的线性回归与非线性回归

一元线性回归 回归分析用来建立方程模拟两个或者多个变量之间如何关联 一元线性回归包括一个自变量和一个因变量 如果包含两个以上的自变量&#xff0c;则称为多元线性回归 代价函数&#xff08;损失函数&#xff09; 损失函数的最终目的是为了使得误差平方和最小 用梯度下…

【装包拆包----泛型】

文章目录 装箱和拆箱泛型创建一个泛型数组泛型的上界泛型方法 装箱和拆箱 装箱&#xff1a; 把基本数据类型给到引用数据类型 public static void main(String[] args) {//自动装包//第一种装包Integer c 12;//第二种装包int a 7;Integer b a;//显示装包Integer aa Intege…

大语言模型|人工智能领域中备受关注的技术

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️其他领域】 文章目录 前言关于大语言模型大语言模型是什么&#xff1f;大语言模型有什么用?文案写作知识库回答文本分类代码生成 AWS 如何通过 LLM 提供帮助&#xff1f;Amazon BedrockAmazon SageM…

QT day3作业

1.思维导图 2、 完善对话框&#xff0c;点击登录对话框&#xff0c;如果账号和密码匹配&#xff0c;则弹出信息对话框&#xff0c;给出提示”登录成功“&#xff0c;提供一个Ok按钮&#xff0c;用户点击Ok后&#xff0c;关闭登录界面&#xff0c;跳转到其他界面 如果账号和密…

【Oracle 客户端连接数据库过程解析】

文章目录 一、开篇二、Oracle客户端简介三、连接过程解析 一、开篇 Oracle数据库以其卓越的性能和稳定性赢得了众多企业的信赖。作为开发者或数据库管理员&#xff0c;理解Oracle客户端如何与数据库建立连接&#xff0c;是确保系统正常运行的关键。 二、Oracle客户端简介 首…

LabVIEW进行MQTT通信及数据解析

需求&#xff1a;一般通过串口的方式进行数据的解析&#xff0c;但有时候硬件的限制&#xff0c;没法预留串口&#xff0c;那么如何通过网络的方式特别是MQTT数据的通信及解析 解决方式&#xff1a; 1.MQTT通信控件&#xff1a; 参考开源的mqtt-LabVIEW https://github.com…

PostGIS学习教程七:关于几何图形的练习

文章目录 一、函数列表二、练习 一、函数列表 以下是我们迄今为止看到的所有函数的汇总&#xff0c;它们应该对练习有用&#xff01; sum(expression) aggregate to return a sum for a set of records count(expression) aggregate to return the size of a set of records …