技术成神之路:设计模式(十八)适配器模式
介绍
适配器模式(Adapter Pattern)是一种结构型设计模式,它允许接口不兼容的类可以协同工作,通过将一个类的接口转换成客户端所期望的另一个接口,使得原本由于接口不兼容而不能一起工作的类可以一起工作。
1.定义
适配器模式将一个类的接口转换成客户期望的另一个接口,使得原本接口不兼容而无法一起工作的类可以一起工作。
2. 主要作用
- 接口兼容:使得两个不兼容的接口能够工作在一起。
- 解耦:通过适配器将客户端与被适配者解耦,减少了系统的耦合性。
- 重用性:允许现有的类在不修改的情况下被复用,提高了代码的重用性。
3. 解决的问题
- 当现有类的接口和需求的接口不兼容时,适配器模式可以将现有接口转换成所需接口。
- 在不修改现有类的前提下,使其能够适应新的接口需求,充分复用现有代码。
4. 模式原理
包含角色:
- Target(目标接口): 客户端期望的接口。
- Adapter(适配器): 实现了目标接口,并且持有一个被适配对象的实例。
- Adaptee(被适配的类): 原本存在的接口或类。
UML类图:

代码示例:
// 目标接口
interface Printer {void print(String content);
}// 旧类(不兼容的接口)
class OldPrinter {void printText(String text) {System.out.println("OldPrinter: " + text);}
}// 适配器类
class PrinterAdapter implements Printer {private OldPrinter oldPrinter;public PrinterAdapter(OldPrinter oldPrinter) {this.oldPrinter = oldPrinter;}@Overridepublic void print(String content) {// 在适配器中处理图像打印的逻辑String textContent = convertImageToText(content);oldPrinter.printText(textContent);}// 假设这是一个将图像转换为文本的方法private String convertImageToText(String image) {return "Converted Image: " + image;}
}
调用
public class AdapterPatternDemo {public static void main(String[] args) {OldPrinter oldPrinter = new OldPrinter();Printer printerAdapter = new PrinterAdapter(oldPrinter);// 客户端使用适配器打印图像printerAdapter.print("SampleImage.jpg");}
}
打印输出
OldPrinter: Converted Image: SampleImage.jpg
适配器在我们的生活中无处不在,帮助不同系统、设备和协议之间实现兼容与互通比如电源适配器,耳机适配器,家用电器的转换插头,文件格式转换等等…
正如你想的那样,将一种不可使用的东西,通过一系列适配达到可用状态,这就是适配器模式的含义。
在Java中InputStreamReader可以被视为适配器,将字节流(InputStream)转换为字符流(Reader)
InputStream inputStream = new FileInputStream("xxx.txt");
Reader reader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(reader);
Java的集合框架中,Collections类提供了多个适配器方法,例如ListIterator。它允许对List集合进行双向迭代。
List<String> list = new ArrayList<>();ListIterator<String> iterator = list.listIterator();while (iterator.hasNext()) {System.out.println(iterator.next());}
在安卓中,适配器的含义是将数据转化成UI显示出来。例如RecyclerView.Adapter是一个典型的适配器模式示例。RecyclerView本身并不知道数据的来源,适配器充当了RecyclerView和数据之间的桥梁。
其实适配器真没啥介绍的,大家已经熟悉的不能再熟悉了,此篇文章就当用来帮助大家加固下对适配器模式的印象吧!😜
5. 优缺点
优点:
- 单一职责原则:将接口转换代码封装在适配器中,不需要修改原有类。
- 开闭原则:添加新的适配器,不需要修改已有代码。
- 提高复用性:可以复用现有类,减少代码重复。
缺点:
- 复杂性增加:引入适配器模式会增加系统的复杂性,增加了额外的类。
- 类适配器的局限性:类适配器使用多重继承,可能不适用于所有面向对象语言(如Java只支持单继承)。
6. 应用场景
- 需要与不兼容的接口或类库进行集成。
- 需要使用现有类的功能,但它们的接口不符合客户端的要求。
- 在系统中需要将多个不同的接口统一为一个接口。
7. 对象适配器(Object Adapter)和类适配器(Class Adapter)区别
| 特性 | 类适配器(Class Adapter) | 对象适配器(Object Adapter) |
|---|---|---|
| 实现方式 | 通过继承(类) | 通过组合(对象) |
| 适配方式 | 编译时适配 | 运行时适配 |
| 灵活性 | 不够灵活,适配关系固定 | 灵活,适配对象可以在运行时更改 |
| 对变化的影响 | 被适配类变化影响较大 | 被适配类变化影响较小 |
8. 总结
适配器模式是一种结构型设计模式,通过将一个类的接口转换为客户端期望的接口,使得原本不兼容的类可以一起工作。它主要解决接口不兼容的问题,提高代码的复用性和灵活性。虽然引入了额外的复杂性,但它在需要复用现有代码,或者在不修改源代码的前提下适应新接口需求的场景下,非常有用。适配器模式有类适配器和对象适配器两种实现方式,各自有优缺点,选择时应根据具体需求和语言特性来决定。
相关文章:
技术成神之路:设计模式(十八)适配器模式
介绍 适配器模式(Adapter Pattern)是一种结构型设计模式,它允许接口不兼容的类可以协同工作,通过将一个类的接口转换成客户端所期望的另一个接口,使得原本由于接口不兼容而不能一起工作的类可以一起工作。 1.定义 适配…...
图神经网络:处理复杂关系结构与图分类任务的强大工具
创作不易,您的打赏、关注、点赞、收藏和转发是我坚持下去的动力! 图神经网络(Graph Neural Network, GNN)是针对图数据的一类神经网络模型。图数据具有节点(节点代表实体)和边(边代表节点之间的…...
LeetCode: 1971. 寻找图中是否存在路径
寻找图中是否存在路径 原题 有一个具有 n 个顶点的 双向 图,其中每个顶点标记从 0 到 n - 1(包含 0 和 n - 1)。图中的边用一个二维整数数组 edges 表示,其中 edges[i] [ui, vi] 表示顶点 ui 和顶点 vi 之间的双向边。 每个顶点…...
mysql 查询表所有数据,分页的语句
在 MySQL 中,若要从表中查询所有数据并实现分页,你可以使用 SELECT 语句结合 LIMIT 和 OFFSET 子句。LIMIT 用于指定返回的记录数,而 OFFSET 则用于指定从哪一条记录开始返回(即跳过的记录数)。 以下是一个基本的分页…...
TI DSP TMS320F280025 Note13:CPUtimer定时器原理分析与使用
TMS320F280025 CPUtimer定时器原理分析与使用 ` 文章目录 TMS320F280025 CPUtimer定时器原理分析与使用框图分析定时器中断定时器使用CPUtimers.cCPUtimers.h框图分析 定时器框图如图所示 定时器有一个预分频模块和一个定时/计数模块, 其中预分频模块包括一个 16 位的定时器分…...
Australis 相機率定軟體說明
概要 課堂中使用Australis這套軟體,順帶記錄操作過程 內容以老師口述及我測試的經過 照片為老師課堂提供之 說明 執行 Step1. 匯入照片 注意!!如果是Mac的作業系統,將資料夾移到Windows上的時候,建議創一個新的資料…...
C++入门(有C语言基础)
string类 string类初始化的方式大概有以下几种: string str1;string str2 "hello str2";string str3("hello str3");string str4(5, B);string str5[3] {"Xiaomi", "BYD", "XPeng"};string str6 str5[2];str…...
第四届高性能计算与通信工程国际学术会议(HPCCE 2024)
目录 大会简介 主办单位,承办单位 征稿主题 会议议程 参会方式 大会官网:www.hpcce.net 大会简介 第四届高性能计算与通信工程国际学术会议(HPCCE 2024)将于2024年11月22-24日在苏州召开。HPCCE 2024将围绕“高性能计算与通信工…...
负载均衡架构解说
负载均衡架构是一种设计模式,用于在多个服务器之间分配网络或应用流量,以提高资源利用率、最大化吞吐量、减少响应时间,并确保高可用性。 负载均衡架构的关键组件和概念: 关键组件 1.负载均衡器(Load Balancer&…...
【异常数据检测】孤立森林算法异常数据检测算法(数据可视化 Matlab语言)
摘要 本文研究了基于孤立森林算法的异常数据检测方法,并在MATLAB中实现了该算法的可视化。孤立森林是一种无监督的异常检测算法,主要通过构建决策树来区分正常数据和异常数据。本文使用真实数据集,通过二维可视化展示了检测结果。实验结果表…...
MKV转MP4丨FFmpeg的简单命令使用——视频格式转换
MKV是一种视频封装格式,很好用,也是OBS的默认推荐录制格式,因为不会突然断电关机而导致整个视频录制文件丢失。 但是MKV无法直接导入PR中剪辑,最直接的方法是将MKV转换为MP4格式,最方便且安全无损的转换方法便是用FFmp…...
git使用“保姆级”教程4——版本回退及分支讲解
一、版本回退 1、历史回退(版本回退)——命令行git reset --hard 版本编号 注意:当前命令会让工作区的内容发生改变,可以理解成历史区(master分支)直接回到工作区比如:从版本4回到版本3,则工作区只会显示版本3的代码内容 1.1、指…...
spring cache,Spring data redis
本项目使用Redis存储缓存数据,如何通过Java去访问Redis? 常用的有Jedis和Lettuce两个访问redis的客户端类库 ,Jedis和Lettuce都是redis提供的。其中Lettuce的性能和并发性要好一些,Spring Boot 默认使用的是 Lettuce 作为 Redis …...
10.数据结构与算法-线性表的应用(线性表与有序表的合并)
线性表的合并 有序表的合并 顺序表 链表...
GAN|对抗| 生成器更新|判别器更新过程
如上图所示,生成对抗网络存在上述内容: 真实数据集;生成器;生成器损失函数;判别器;判别器损失函数;生成器、判别器更新(生成器和判别器就是小偷和警察的关系,他们共用的…...
day01——登录功能
逻辑: 前端将登录信息通过报文的形式,发送给后端。后端进行登陆验证 2.1 根据接受的用户名,查询数据表。 若不存在该用户的记录,返回用户不存在。 若用户存在,判断数据库中的密码和接收的是否一致,不一致则…...
Flutter中使用FFI的方式链接C/C++的so库(harmonyos)
Flutter中使用FFI的方式链接C/C库(harmonyos) FFI plugin创建和so的配置FFI插件对so库的使用 FFI plugin创建和so的配置 首先我们可以根据下面的链接生成FFI plugin插件:开发FFI plugin插件 然后在主项目中pubspec.yaml 添加插件的依赖路径&…...
【C++】二义性
在C中,二义性(ambiguity)通常指的是编译器无法确定使用哪个函数、变量或类成员的情况。这种不确定性通常是由于继承和多态特性导致的。下面是一些常见的产生二义性的场景以及如何解决它们的方法: 1. 多重继承中的二义性 当一个类…...
高并发内存池(五):ThreadCache、CentralCache和PageCache的内存回收机制、阶段性代码展示和释放内存过程的调试
目录 ThreadCache的内存回收机制 补充内容1 补充内容2 补充内容3 补充内容4 ListTooLong函数的实现 CentralCache的内存回收机制 MapObjectToSpan函数的实现 ReleaseListToSpans函数的实现 PageCache的内存回收机制 补充内容1 补充内容2 ReleaseSpanToPageCache函…...
STL之stackqueue篇(上)探索C++ STL中的Queue与Stack——构建数据处理的基础框架
文章目录 前言一、stack1.1 定义与基本概念1.2 底层容器1.3 成员函数1.4 使用示例1.5 注意事项1.6 应用场景 二、queue2.1 定义与基本概念2.2 底层容器2.3 成员函数2.4 使用示例2.5 注意事项2.6 应用场景 前言 本文旨在深入探讨C STL中的queue与stack容器,从它们的…...
AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...
华为OD机试-食堂供餐-二分法
import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...
视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...
uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...
LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》
这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...
