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

【深入理解设计模式】适配器设计模式

在这里插入图片描述

适配器设计模式

适配器设计模式是一种结构型设计模式,用于将一个类的接口转换成客户端所期望的另一个接口,从而使得原本由于接口不兼容而不能一起工作的类能够一起工作。适配器模式通常用于以下场景:

  1. 现有接口与需求不匹配:当需要使用的类的接口与当前系统的接口不匹配时,可以创建一个适配器来进行转换。

  2. 类的功能需要增强:有时候,为了增强现有类的功能而不修改原有代码,可以使用适配器模式。

概述

如果去欧洲国家去旅游的话,他们的插座如下图最左边,是欧洲标准。而我们使用的插头如下图最右边的。因此我们的笔记本电脑,手机在当地不能直接充电。所以就需要一个插座转换器,转换器第1面插入当地的插座,第2面供我们充电,这样使得我们的插头在当地能使用。生活中这样的例子很多,手机充电器(将220v转换为5v的电压),读卡器等,其实就是使用到了适配器模式。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

定义:

​ 将一个类的接口转换成客户端希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。

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

结构

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

  • 目标(Target)接口:当前系统业务所期待的接口,它可以是抽象类或接口。
  • 被适配者(Adaptee):需要被适配的类。它定义了适配器所需的原始接口。
  • 适配器(Adapter)类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。

适配器模式的实现可以分为两种方式:

  • 类适配器模式:通过继承被适配类和实现目标接口来实现适配器。这种方式需要多重继承或接口实现,不过在一些编程语言中并不支持多重继承,因此并不常用。

  • 对象适配器模式:通过在适配器类中组合或聚合被适配类的实例来实现适配器。这种方式更加灵活,因为它可以适配多个类而不仅限于单一类。

适配器设计模式能够很好地解决不同接口之间的兼容性问题,使得原本不兼容的类能够协同工作,提高了代码的复用性和灵活性。

类适配器模式

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

【例】读卡器

现有一台电脑只能读取SD卡,而要读取TF卡中的内容的话就需要使用到适配器模式。创建一个读卡器,将TF卡中的内容读取出来。

代码如下:

/*** @author OldGj 2024/02/23* @version v1.0* @apiNote 电脑类*/
public class Computer {// 向SD卡中写数据(目标接口只能是SDCard)public void writeSD(SDCard sdCard, String msg) {sdCard.writeMsg(msg);}// 从SD卡中读取数据(目标接口只能是SDCard)public String readSD(SDCard sdCard) {return sdCard.readMsg();}
}
/*** @author OldGj 2024/02/23* @version v1.0* @apiNote 目标接口 - SD卡接口*/
public interface SDCard {// 向SD卡中写数据void writeMsg(String msg);// 从SD卡中读数据String readMsg();}
/*** @author OldGj 2024/02/23* @version v1.0* @apiNote 目标接口实现类 - SDCard实现类*/
public class SDCardImpl implements SDCard{@Overridepublic void writeMsg(String msg) {System.out.println("write msg to sd card"+msg);}@Overridepublic String readMsg() {return "read msg from sd card";}
}
/*** @author OldGj 2024/02/23* @version v1.0* @apiNote 适配者 - TFCard*/
public interface TFCard {// 向TF卡中写数据void writeMsg(String msg);// 从TF卡中读数据String readMsg();}
/*** @author OldGj 2024/02/23* @version v1.0* @apiNote 具体适配者 - TFCard具体实现类*/
public class TFCardImpl implements TFCard{@Overridepublic void writeMsg(String msg) {System.out.println("write msg to tf card"+msg);}@Overridepublic String readMsg() {return "read msg from tf card";}
}

/*** @author OldGj 2024/02/23* @version v1.0* @apiNote 适配器类 继承被适配者类 实现目标接口*/
public class SDAdapterTF extends TFCardImpl implements SDCard{@Overridepublic void writeMsg(String msg) {super.writeMsg(msg);}@Overridepublic String readMsg() {return super.readMsg();}
}
/*** @author OldGj 2024/02/23* @version v1.0* @apiNote 客户端 - 测试类*/
public class Client {public static void main(String[] args) {Computer computer = new Computer();SDCard sdCard = new SDCardImpl();String s = computer.readSD(sdCard);System.out.println(s);System.out.println("=============");// 通过适配器,将TF卡转换为实现SD接口的适配器SDAdapterTF adapterTF = new SDAdapterTF();// 读取适配器中的数据String s1 = computer.readSD(adapterTF);System.out.println(s1);}
}

类适配器模式违背了合成复用原则。类适配器是客户类有一个接口规范的情况下可用,反之不可用。

对象适配器模式

实现方式:对象适配器模式可釆用将现有组件库中已经实现的组件引入适配器类中,该类同时实现当前系统的业务接口。

【例】读卡器

我们使用对象适配器模式将读卡器的案例进行改写。

类适配器模式的代码,我们只需要修改适配器类(SDAdapterTF)和测试类。

/*** @author OldGj 2024/02/23* @version v1.0* @apiNote 适配器类 继承适配者类 实现目标接口*/
public class SDAdapterTF implements SDCard {private TFCard tfCard;public SDAdapterTF(TFCard tfCard) {this.tfCard = tfCard;}@Overridepublic void writeMsg(String msg) {tfCard.writeMsg(msg);}@Overridepublic String readMsg() {return tfCard.readMsg();}
}
/*** @author OldGj 2024/02/23* @version v1.0* @apiNote 客户端 - 测试类*/
public class Client {public static void main(String[] args) {Computer computer = new Computer();SDCard sdCard = new SDCardImpl();String s = computer.readSD(sdCard);System.out.println(s);System.out.println("=============");// 将TF卡传入适配器中SDAdapterTF sdAdapterTF = new SDAdapterTF(new TFCardImpl());String s1 = computer.readSD(sdAdapterTF);System.out.println(s1);}
}

注意:还有一个适配器模式是接口适配器模式。当不希望实现一个接口中所有的方法时,可以创建一个抽象类Adapter ,实现所有方法。而此时我们只需要继承该抽象类即可。

应用场景

  • 以前开发的系统存在满足新系统功能需求的类,但其接口同新系统的接口不一致。
  • 使用第三方提供的组件,但组件接口定义和自己要求的接口定义不同。

JDK中的适配器模式:

当涉及字符流(Reader)和字节流(InputStream)之间的适配时,通常会使用适配器模式。这种适配器模式的目的是让字符流和字节流能够协同工作,尽管它们的接口不同。

  1. Reader(字符流)Reader 是 Java 中用于读取字符流的抽象基类。它定义了读取字符数据的一系列方法,如 read()close() 等。字符流是以字符为单位进行读取和写入的,对文本数据的处理更为方便。

  2. InputStream(字节流)InputStream 是 Java 中用于读取字节流的抽象基类。它定义了读取字节数据的一系列方法,如 read()close() 等。字节流是以字节为单位进行读取和写入的,适用于处理二进制数据。

  3. InputStreamReader(适配器)InputStreamReader 是 Java 中用于将字节流转换为字符流的适配器类。它实现了 Reader 接口,并包装了一个 InputStream 对象。InputStreamReader 通过在字节流和字符流之间进行转换,使得字符流能够读取字节流中的数据。它的作用就是将字节流适配成字符流,使得原本不兼容的字符流和字节流能够一起工作。

在使用 InputStreamReader 时,它会接受一个 InputStream 对象作为参数,并将该对象转换为字符流,因此它充当了字符流和字节流之间的适配器。这样一来,当我们需要使用字符流操作时,可以直接使用 Reader 接口及其实现类,而不必直接操作字节流。InputStreamReader 负责将底层的字节流适配成字符流,从而实现了字符流和字节流之间的适配。

总而言之,ReaderInputStream 之间的适配器模式的典型应用就是通过 InputStreamReader 将字节流适配成字符流,使得字符流和字节流能够协同工作,这是适配器模式在 Java IO 中的一个典型应用。

相关文章:

【深入理解设计模式】适配器设计模式

适配器设计模式 适配器设计模式是一种结构型设计模式,用于将一个类的接口转换成客户端所期望的另一个接口,从而使得原本由于接口不兼容而不能一起工作的类能够一起工作。适配器模式通常用于以下场景: 现有接口与需求不匹配:当需要…...

ASP.NET-实现图形验证码

ASP.NET 实现图形验证码能够增强网站安全性,防止机器人攻击。通过生成随机验证码并将其绘制成图像,用户在输入验证码时增加了人机交互的难度。本文介绍了如何使用 C# 和 ASP.NET 创建一个简单而有效的图形验证码系统,包括生成随机验证码、绘制…...

解决Maven爆红以及解决 Idea 卡在 Resolving问题

关于 Idea 卡在 Resolving(前提是Maven的setting.xml中配置好了阿里云和仓库) 参考文章https://blog.csdn.net/jiangyu1013/article/details/95042611 解决Maven爆红参考文章https://devpress.csdn.net/beijing/656d993b76f0791b6eca7bb0.html?dp_toke…...

MySQL集群 双主架构(配置命令)

CSDN 成就一亿技术人&#xff01; 今天刚开学第一天给大家分享一期&#xff1a;MySQL集群双主的配置需求和命令 CSDN 成就一亿技术人&#xff01; 神秘泣男子主页&#xff1a;作者首页 <———— MySQL专栏 &#xff1a;MySQL数据库专栏<———— MySQL双主是一…...

网络安全之安全事件监测

随着人们对技术和智能互联网设备依赖程度的提高&#xff0c;网络安全的重要性也在不断提升。因此&#xff0c;我们需要不断加强网络安全意识和措施&#xff0c;确保网络环境的安全和稳定。 网络安全的重要性包含以下几点&#xff1a; 1、保护数据安全&#xff1a;数据是组织和…...

【BUG 记录】MyBatis-Plus 处理枚举字段和 JSON 字段

【BUG 记录】MyBatis-Plus 处理枚举字段和JSON字段 一、枚举字段&#xff08;mysql环境已测、postgresql环境已测&#xff09;1.1 场景1.2 定义枚举常量1.3 配置枚举处理器1.4 测试 二、JSON字段&#xff08;mysql环境已测&#xff09;2.1 导包2.2 使用对象接受2.3 测试 三、JS…...

Web性能优化-详细讲解与实用方法-MDN文档学习笔记

Web性能优化 查看更多学习笔记&#xff1a;GitHub&#xff1a;LoveEmiliaForever MDN中文官网 性能优良的网站能够提高访问者留存和用户满意度&#xff0c;减少客户端和服务器之间传输的数据量可降低各方的成本 不同的业务目标和用户需求需要不同的性能度量&#xff0c;要提高…...

组态王连接施耐德M580PLC

组态王连接施耐德M580 网络架构 网线连接PLC和装组态王软件的PC组态设置帮助 可先查看帮助&#xff1a;菜单栏点击【帮助】->【驱动帮助】&#xff0c;在弹出窗口中PLC系列选择莫迪康PLC的“modbusRtu\ASSCII\TCP”查看组态配置流程&#xff1a; 相关说明&#xff1a; 1、…...

pop链构造 [NISACTF 2022]babyserialize

打开题目 题目源代码如下 <?php include "waf.php"; class NISA{public $fun"show_me_flag";public $txw4ever;public function __wakeup(){if($this->fun"show_me_flag"){hint();}}function __call($from,$val){$this->fun$val[0];…...

【VIP专属】Python应用案例——基于Keras, OpenCV和MobileNet口罩佩戴识别

目录 1、导入所需库 2、加载人脸口罩检测数据集 3、对标签进行独热编码...

Doris——荔枝微课统一实时数仓建设实践

目录 一、业务介绍 二、早期架构及痛点 2.1 早期架构 2.2 架构痛点 三、技术选型 四、新的架构及方案 五、搭建经验 5.1 数据建模 5.2 数据开发 5.3 库表设计 5.4 数据管理 5.4.1 监控告警 5.4.2 数据备份与恢复 六、收益总结 七、未来规划 原文大佬这篇Doris腾…...

Stable Diffusion 绘画入门教程(webui)-ControlNet(Inpaint)

上篇文章介绍了语义分割Tile/Blur&#xff0c;这篇文章介绍下Inpaint&#xff08;重绘&#xff09; Inpaint类似于图生图的局部重绘&#xff0c;但是Inpain效果要更好一点&#xff0c;和原图融合会更加融洽&#xff0c;下面是案例&#xff0c;可以看下效果&#xff08;左侧原图…...

LeetCode146: LRU缓存

题目描述 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类&#xff1a; LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存 int get(int key) 如果关键字 key 存在于缓存中&#xff0c;则返回关键字的值&#xff0c;否则…...

【ArcGIS】基于DEM/LUCC等数据统计得到各集水区流域特征

基于DEM/LUCC等数据统计得到各集水区流域特征 提取不同集水区各类土地利用类型比例步骤1&#xff1a;划分集水区为独立面单元步骤2&#xff1a;批量掩膜提取得到各集水区土地利用类型比例步骤3&#xff1a;导入各集水区LUCC数据并统计得到各类型占比 提取坡度特征流域面坡度河道…...

vue3中安装并使用CSS预处理器Sass的方法介绍

文章目录 Sass是什么&#xff1f;为什么使用Sass?安装sass1、安装sass2、编写全局css变量/全局mixin3、vite引入并使用4、按需引入并使用 sass语法1、变量创建一个变量使用变量变量作用域 2、数学计算两个Sass有关于数学计算的“陷阱” 3、嵌套4、Imports sass中文官网 Sass是…...

过滤器(Filter)

过滤器&#xff08;Filter&#xff09; 1. 基本概念 过滤器&#xff08;Filter&#xff09;是拦截 Request 请求的对象&#xff1a;在用户的请求访问资源前处理 ServletRequest 和 ServletResponse 。 Filter 相关的接口有&#xff1a;Filter、FilterConfig、FilterChain 。…...

AMRT3D数字孪生引擎详解

AMRT 3D数字孪生引擎介绍 AMRT3D引擎是一款融合了眸瑞科技的AMRT格式与轻量化处理技术为基础&#xff0c;以降本增效为目标&#xff0c;支持多端发布的一站式纯国产自研的CS架构项目开发引擎。 引擎包括场景搭建、UI拼搭、零代码交互事件、光影特效组件、GIS/BIM组件、实时数据…...

Sqlite数据库详解

1.关于Sqlite SQLite 是一个进程内库&#xff0c;它实现了一个独立的、无服务器的、零配置的事务性 SQL 数据库引擎。 SQLite的代码属于公共领域&#xff0c;因此对 用于任何目的&#xff0c;商业或私人目的。 SQLite是世界上部署最广泛的数据库 应用程序比我们能做的要多 计数…...

基于YOLOv8深度学习+Pyqt5的电动车头盔佩戴检测系统

wx供重浩&#xff1a;创享日记 对话框发送&#xff1a;225头盔 获取完整源码源文件已标注的数据集&#xff08;1463张&#xff09;源码各文件说明配置跑通说明文档 若需要一对一远程操作在你电脑跑通&#xff0c;有偿59yuan 效果展示 基于YOLOv8深度学习PyQT5的电动车头盔佩戴检…...

【数据结构】B树,B+树,B*树

文章目录 一、B树1.B树的定义2.B树的插入3.B树的中序遍历 二、B树和B*树1.B树的定义2.B树的插入3.B*树的定义4.B树系列总结 三、B树与B树的应用 一、B树 1.B树的定义 1. 在内存中搜索效率高的数据结构有AVL树&#xff0c;红黑树&#xff0c;哈希表等&#xff0c;但这是在内存…...

揭秘AI写教材的秘诀,低查重AI教材编写工具让你的创作之路畅通无阻!

教材初稿的完成是个喜事&#xff0c;但随之而来的修改和优化过程却让人感到无比痛苦&#xff01;细致地阅读每个字句以找出逻辑错误或知识不准确的地方&#xff0c;确实需要消耗大量的时间&#xff1b;而对某一章节结构的调整&#xff0c;往往会影响到后续的多个部分&#xff0…...

DownKyi终极指南:免费高效获取B站视频的完整教程

DownKyi终极指南&#xff1a;免费高效获取B站视频的完整教程 【免费下载链接】downkyi 哔哩下载姬downkyi&#xff0c;哔哩哔哩网站视频下载工具&#xff0c;支持批量下载&#xff0c;支持8K、HDR、杜比视界&#xff0c;提供工具箱&#xff08;音视频提取、去水印等&#xff09…...

别再死记硬背了!用动画图解二叉排序树的插入与删除(附C++代码调试技巧)

动画拆解二叉排序树&#xff1a;从插入删除到调试实战 二叉排序树是数据结构中最经典的平衡与搜索思想的结合体&#xff0c;但很多初学者在理解插入和删除操作时&#xff0c;常常陷入机械记忆的困境。本文将通过动画分步演示和IDE调试技巧&#xff0c;带您真正掌握二叉排序树的…...

别再混淆SNR和Eb/N0了!用Wi-Fi 6(802.11ax)实测数据讲透数字通信核心指标

从Wi-Fi 6实测数据透视数字通信核心指标&#xff1a;SNR与Eb/N0的本质差异 在调试一台支持Wi-Fi 6的路由器时&#xff0c;工程师小张发现了一个奇怪现象&#xff1a;当信号强度显示为-65dBm时&#xff0c;实测吞吐量在不同频段竟相差30%。这个案例揭示了通信系统中一个关键认知…...

RimWorld Mod开发进阶:用状态机重构你的集群AI,告别行为树死板流程

RimWorld Mod开发进阶&#xff1a;用状态机重构集群AI的实战指南 在RimWorld的Mod开发中&#xff0c;AI行为设计一直是开发者面临的核心挑战之一。原生行为树系统虽然易于上手&#xff0c;但当我们需要实现复杂的多阶段动态事件时&#xff0c;其线性执行的局限性就会暴露无遗。…...

你是一名Java程序员,重载的方法有什么区别

你是一名Java程序员&#xff0c;重载的方法有什么区别 作为一名Java程序员&#xff0c;很高兴为你解答这个问题。 在 Java 中&#xff0c;重载&#xff08;Overload&#xff09; 指的是在同一个类中定义多个名称相同但参数列表不同的方法。这就像你有一个“打印”功能&#xff…...

DeepLabV3+特征融合实战:为什么浅层特征对边缘分割这么重要?

DeepLabV3特征融合实战&#xff1a;浅层特征如何成为边缘分割的胜负手 当你在人像分割任务中发现发丝边缘总是模糊不清&#xff0c;或在道路分割项目中遇到路沿识别精度不足时&#xff0c;问题的根源往往不在于模型的整体架构&#xff0c;而在于那些容易被忽视的浅层特征。Dee…...

海康ISAPI接口调优笔记:如何正确设置NET_DVR_STDXMLConfig的超时与缓冲区,避免数据截断和线程卡死

海康ISAPI接口调优实战&#xff1a;NET_DVR_STDXMLConfig参数配置与高并发优化策略 在工业级监控系统与智慧园区解决方案中&#xff0c;海康威视设备的ISAPI接口集成往往是核心环节。许多开发者在使用NET_DVR_STDXMLConfig进行透传调用时&#xff0c;常会遇到数据截断、线程阻塞…...

抖音批量下载终极神器:三分钟搞定无水印视频采集

抖音批量下载终极神器&#xff1a;三分钟搞定无水印视频采集 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback support. 抖…...

IUV全网元协同排障实战:从无线侧到核心网的典型配置错点解析

1. 从"用户无法接入5G网络"说起&#xff1a;一个典型故障的排查起点 上周遇到个挺有意思的案例&#xff1a;某运营商新建的5G SA网络完成部署后&#xff0c;测试终端始终显示"无服务"状态。这个看似简单的现象背后&#xff0c;其实藏着从无线侧到核心网可能…...