适配器模式在Java开发中的应用
适配器模式(Adapter Pattern)是设计模式中的一种结构型模式,它允许将一个类的接口转换成客户端所期望的另一个接口。通过这种方式,原本因接口不兼容而无法协同工作的类能够一起工作。适配器模式在Java开发中非常常见,尤其是在系统集成、接口重构或扩展现有功能时。
本文将详细讲解适配器模式的结构、类型、使用场景,并结合具体的代码示例来说明其在Java开发中的应用。
适配器模式的结构
适配器模式主要由以下几个核心角色组成:
-
目标接口(Target)
这是客户端所期望的接口,定义了客户端希望调用的方法。 -
适配者(Adaptee)
需要被适配的现有类或接口,它提供了实际的功能,但其接口与目标接口不兼容。 -
适配器(Adapter)
适配器类负责实现目标接口,并通过调用适配者的方法来完成接口转换。
适配器模式的类型
适配器模式有两种实现方式:
-
类适配器
通过继承适配者类并实现目标接口来完成适配。由于Java是单继承语言,这种方式较少使用。 -
对象适配器
通过组合的方式持有适配者对象的实例,并实现目标接口。这种方式更灵活,在Java开发中更为常用。
本文将重点介绍对象适配器,因为它更符合Java的设计理念。
使用场景
适配器模式适用于以下几种常见场景:
-
接口不兼容问题
系统需要使用一个现有的类,但该类的接口不符合当前需求。 -
代码复用
希望创建一个可复用的类,使其能与多个不同的接口协同工作。 -
无侵入式扩展
在不修改现有代码的情况下,扩展系统的功能,例如适配旧系统到新接口。
例如,在遗留系统升级、第三方库整合或日志框架转换等场景中,适配器模式都能发挥重要作用。
代码示例与具体场景
下面通过一个具体的例子来展示适配器模式在Java开发中的应用。
场景描述
假设我们有一个旧的日志记录类 OldLogger
,它提供了一个简单的 log
方法:
public class OldLogger {public void log(String message) {System.out.println("Old Logger: " + message);}
}
现在,系统升级后定义了一个新的日志接口 NewLogger
,要求支持区分信息日志和错误日志:
public interface NewLogger {void logInfo(String message);void logError(String message);
}
我们的目标是复用 OldLogger
的功能,使其适配 NewLogger
接口,而不修改 OldLogger
的代码。
解决方案:对象适配器
我们可以创建一个适配器类 LoggerAdapter
,实现 NewLogger
接口,并通过组合的方式持有 OldLogger
的实例:
public class LoggerAdapter implements NewLogger {private OldLogger oldLogger;// 通过构造函数注入OldLogger实例public LoggerAdapter(OldLogger oldLogger) {this.oldLogger = oldLogger;}@Overridepublic void logInfo(String message) {oldLogger.log("INFO: " + message);}@Overridepublic void logError(String message) {oldLogger.log("ERROR: " + message);}
}
客户端使用
客户端代码可以通过 NewLogger
接口调用适配器,而无需关心底层实现:
public class Client {public static void main(String[] args) {// 创建OldLogger实例OldLogger oldLogger = new OldLogger();// 使用适配器包装OldLoggerNewLogger newLogger = new LoggerAdapter(oldLogger);// 调用新接口方法newLogger.logInfo("This is an info message.");newLogger.logError("This is an error message.");}
}
输出结果
运行上述代码,将得到以下输出:
Old Logger: INFO: This is an info message.
Old Logger: ERROR: This is an error message.
代码分析
-
目标接口(NewLogger)
定义了客户端期望的logInfo
和logError
方法。 -
适配者(OldLogger)
提供了旧的log
方法,是需要被适配的类。 -
适配器(LoggerAdapter)
实现了NewLogger
接口,并通过持有的OldLogger
实例,将新接口的调用转换为旧接口的调用。
这种方式不仅复用了 OldLogger
的功能,还满足了新接口的要求,同时保持了代码的低耦合性和可扩展性。
实际开发中的应用场景
在Java开发中,适配器模式有着广泛的应用,以下是几个典型例子:
-
数据库驱动适配
Java的JDBC API是一个目标接口,不同数据库厂商提供的驱动(如MySQL、Oracle)是适配者,通过适配器模式统一了数据库操作接口。 -
第三方库整合
当项目需要集成一个第三方库,但其API与现有系统不兼容时,可以通过适配器模式封装第三方库的调用。 -
遗留系统迁移
在将旧系统逐步迁移到新架构时,适配器模式可以作为过渡方案,确保新旧代码的无缝衔接。
优点与局限性
优点
- 提高复用性:无需修改现有代码即可复用旧类。
- 灵活性强:通过适配器隔离了客户端与适配者,降低了耦合。
- 符合开闭原则:在扩展功能时无需改动原有代码。
局限性
- 增加复杂度:引入额外的适配器类可能会使系统结构更复杂。
- 性能开销:适配器作为中间层,可能带来轻微的性能损耗。
总结
适配器模式是一种非常实用的设计模式,特别适用于处理接口不兼容的问题。在Java开发中,对象适配器因其灵活性和对组合的偏好而更受欢迎。通过上述代码示例,我们可以看到,适配器模式能够有效地将旧的日志系统适配到新接口,既保留了原有功能的复用,又满足了新的需求。
在实际开发中,当你遇到需要整合不同接口或复用现有代码的场景时,不妨考虑使用适配器模式。它不仅能提高代码的灵活性和可维护性,还能为系统的平滑演进提供支持。
相关文章:
适配器模式在Java开发中的应用
适配器模式(Adapter Pattern)是设计模式中的一种结构型模式,它允许将一个类的接口转换成客户端所期望的另一个接口。通过这种方式,原本因接口不兼容而无法协同工作的类能够一起工作。适配器模式在Java开发中非常常见,尤…...
(三)谷歌Code as Policies复现(操作记录)
目录 《复现的项目来源》 一、创建虚拟环境 二、下载原项目并修改(非必须) 二、可直接下载修改后的项目 三、配置环境 (1)安装jupyterlab以及内核 (2)安装ffmpeg (3)配置环境…...
驱动学习专栏--字符设备驱动篇--2_字符设备注册与注销
对于字符设备驱动而言,当驱动模块加载成功以后需要注册字符设备,同样,卸载驱动模 块的时候也需要注销掉字符设备。字符设备的注册和注销函数原型如下所示 : static inline int register_chrdev(unsigned int major, const char *name, const…...
奥创中心卸载工具Armoury Crate Uninstall Tool官网下载
为了应对用户对 Armoury Crate 占用资源大、卸载困难等问题的普遍反馈,ASUS 官方提供了一个专门的卸载工具,即 Armoury Crate Uninstall Tool(奥创中心卸载工具)。该工具的主要作用是帮助用户彻底从系统中移除 Armoury Crate 相关的所有组件,…...
【Linux网络】网络基础概念深度解析
📢博客主页:https://blog.csdn.net/2301_779549673 📢博客仓库:https://gitee.com/JohnKingW/linux_test/tree/master/lesson 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正! &…...
【NLP 61、大模型应用 —— RAG方法】
生活打不败一个大口吃饭的人! —— 25.4.13 一、模型幻觉问题 模型幻觉(AI Hallucination)是指人工智能模型(尤其是大语言模型)生成看似合理但实际不准确、虚构或与事实不符内容的现象。其本质是模型基于统计概…...
UV工具——小试牛刀
背景 MCP开发使用到 为什么MCP更推荐使用uv进行环境管理? MCP 依赖的 Python 环境可能包含多个模块,uv 通过 pyproject.toml 提供更高效的管理方式,并且可以避免 pip 的一些依赖冲突问题。此外,uv 的包管理速度远超 pip…...
vue3+vite 多个环境配置
同一套代码 再也不用在不同的环境里来回切换请求地址了 然后踩了一个坑 就是env的文件路径是在当前项目下 不是在views内 因为公司项目需求只有dev和pro两个环境 虽然我新增了3个 但是只在这两个里面配置了 .env是可以配置一些公共配置的 目前需求来说不需要 所以我也懒得配了。…...
《分布式软总线架构下,设备虚拟化技术的深度剖析与优化策略》
设备之间的互联互通和协同工作已成为一种趋势。分布式软总线架构作为实现这一目标的关键技术,为不同设备之间的通信和协作提供了基础。而设备虚拟化技术则是在分布式软总线架构下,进一步提升设备资源利用效率的重要手段。本文将深入探讨在分布式软总线架…...
MCP 正当时:FunctionAI MCP 开发平台来了!
作者:封崇 MCP:AI 时代的“操作系统接口” 2024 年 11 月,Anthropic 发布模型上下文协议(MCP),这一开放标准迅速引发开发者社区的"协议觉醒"。其本质是通过标准化接口实现 LLM 与外部世界的双向…...
AI Agents系列之AI代理的类型
在本文中,我们将探讨不同类型的 AI 代理,包括它们的实现、实际应用、优势和局限性。从简单反射代理到多代理系统,我们将了解这些模型如何推动自动化、决策制定和智能问题解决。 文章目录 1. AI代理的类型1.1 简单反射代理1.1.1 实现**1.1.2 优势****1.1.3 局限性**1.2 基于…...
Go RabbitMQ基础教程:入门与实践指南,实战代码讲解
简介: RabbitMQ是一款实现高级消息队列协议(AMQP)的消息代理软件,也称为消息队列或消息中间件。它通过解耦应用程序之间的直接通信,支持异步数据交换,增强了系统的可扩展性和灵活性。RabbitMQ能够跨平台运…...
LeetCode详解之如何一步步优化到最佳解法:27. 移除元素
LeetCode详解系列的总目录(持续更新中): LeetCode详解之如何一步步优化到最佳解法:前100题目录(更新中...)-CSDN博客 LeetCode详解系列的上一题链接: LeetCode详解之如何一步步优化到最佳解法…...
c++原子操作
原子操作,顾名思义,该操作不可分割。多线程环境也能保证读写数据不错乱。百度搜索了下,其核心概念如下: 1、不可分割性。原子操作是指一系列不可被CPU上下文交换的机器指令,操作要么完全执行,要么完全不执…...
在 Redis Lua 脚本中,keyCount 参数的作用是明确区分脚本参数中的 KEYS 和 ARGV,具体关系如下:
在 Redis Lua 脚本中,keyCount 参数的作用是**明确区分脚本参数中的 KEYS 和 ARGV**,具体关系如下: --- ### 核心作用 1. **参数分类标识** - keyCount 表示脚本中使用的 Redis KEY 的数量(即 KEYS 数组的长度)…...
小白如何从0学习CSS
以下是针对小白从零开始系统学习 CSS 的完整路径和实用指南,结合核心概念、实践技巧和项目经验,助你掌握网页样式的精髓: 1. 理解 CSS 是什么? 定义:CSS(层叠样式表)用于控制网页的视觉表现&…...
一文掌握RK3568开发板Android13挂载Windows共享目录
在物联网和边缘计算场景中,开发板与PC端的高效文件交互尤为重要。现以iTOP-RK3568开发板为例,详细演示Android13系统如何通过CIFS协议挂载Windows共享目录,实现开发板与PC的无缝文件共享。 RK3568开发板优势 iTOP-3568开发板采用瑞芯微RK3…...
UE5烘培后->为什么C磁盘满了
烘培会产生ddc 需要把路径切换一下,比如切换到游戏空间下。 如何修改,修改如下: 使用记事本打开BaseEngine.ini文件。 将以下内容: textCopy Code Path\"%ENGINEVERSIONAGNOSTICUSERDIR%DerivedDataCache\" 替换为&…...
本地搭建全网可访问的开源音乐服务器Melody结合内网穿透随时听歌
文章目录 前言1. 添加镜像源2. 本地部署Melody3. 本地访问与使用演示4. 安装内网穿透5. 配置Melody公网地址6. 配置固定公网地址 前言 嗨,各位音乐发烧友们!今天我要带你们解锁一个超酷的新技能——在香橙派Zero3上搭建自己的在线音乐平台,并…...
深度学习Y5周:yolo.py文件解读
🍨 本文为🔗365天深度学习训练营中的学习记录博客🍖 原作者:K同学啊 一、前言 文件位置:./models/yolo.py 此文件是实现YOLOv5网络模型的搭建文件,如果想改进YOLOv5,这个文件是必须进行修改的…...
Qt实现文件传输服务器端(图文详解+代码详细注释)
Qt实现文件传输服务器 1、前言2、服务器2.1 服务器UI界面2.2添加网络模块和头文件2.3、创建服务器对象2.4 连接有新连接的信号与槽2.5实现有新连接处理的槽函数2.6 选择文件按钮实现2.6.1 连接按钮点击的信号与槽2.6.2 添加头文件2.6.3 创建所需对象2.6.3 选择文件按钮实现 2.7…...
记录学习的第二十七天
今天效率低下,只做了一道力扣的每日一题。 看了题解才懂的。下面复述一遍吧。 算法就是越长越合法型滑动窗口。 核心: 如果此时窗口中有c个元素x,此时再进一个x,那么相同数对就增加c个。 如果此时窗口有c个元素x,此…...
docker 安装TDengine 时序数据库
TDengine是一个高性能、分布式a的时序数据库,专为物联网(loT)和大数据分析日设计。使用Docker快速地搭建 TDengine 的开发或测试环境。以下技术指南,帮助您通过Docker Compose 安装并运行TDengine 1.拉取镜像 (3.3.6.0版本) docker pull registry.cn-ha…...
如何更好使用呼叫中心系统和语音机器人
要更好地使用呼叫中心系统和语音机器人,需要结合两者的优势,实现自动化、智能化、高效率的客户服务与业务运营。以下是优化策略和具体实践方法: 一、呼叫中心系统优化 1. 智能路由与IVR优化 智能ACD(自动呼叫分配&…...
C复习(主要复习)
指针和数组 指针数组是一个数组,数组的每个元素都是指针。它适用于需要存储多个指针的场景,如字符串数组。数组指针是一个指针,指向一个数组。它适用于需要传递整个数组给函数或处理多维数组的场景。 函数指针:函数指针的定义需要…...
网页五子棋项目测试报告
一、测试概述 网页五子棋项目运用 Java 语言与 Spring 框架开发,具备用户登录注册、人机对战、在线匹配对局、房间邀请对局及积分排行榜等功能。本次测试旨在评估项目各功能的完整性、稳定性与交互性,依据各文章所描述的功能设计和实现细节进行全面测试…...
大模型提示词prompt
系列文章目录 第一章 提示词的引言和指南 文章目录 系列文章目录前言原则1:写清楚具体的说明1、使用分割符2、要求结构化输出3、检查条件是否满足 检查完成任务所需的假设4、少量样例提示给出成功的例子 原则2:给模型足够的时间思考1、给予模型要输出执…...
如何让Agent开发正真可控、可靠?Cursor AI工程化
工程化的目的 不知道你在AI编程的过程中有没有这样的痛点?开发质量不理想、研发进度无法把控… 问题核心在于没有一套属于AI编程的规范,这正是工程化要解决的问题。 如何工程化 参考我们正常研发流程中的步骤,技术方案设计&评审->…...
计算机视觉——基于人工智能视觉注意力的在线广告中评估检测技术
概述 自2023年在线广告行业估计花费了7403亿美元以来,很容易理解为什么广告公司会投入大量资源进行这一特定领域的计算机视觉研究。 尽管这个行业通常较为封闭和保守,但偶尔也会在arxiv等公共存储库中发布一些研究,这些研究暗示了更先进的专…...
opencv函数展示
一、图像基础 I/O 与显示 1.cv2.imread() 2.cv2.imshow() 3. cv2.waitKey() 4. cv2.imwrite() 5. cv2.selectROI() 6. cv2.VideoCapture() 二、颜色空间与转换 1. cv2.cvtColor() 2. cv2.split() 三、阈值处理 1. cv2.threshold() 2. 特殊阈值方法...
Redis 的不同数据结构分别适用于哪些微服务场景
我们一块来分析下Redis 的不同数据结构在微服务场景下的具体应用: 1. String (字符串) 特点: 最基本的数据类型,二进制安全,可以存储任何类型的数据(文本、序列化对象、图片等),最大 512MB。支持原子性的…...
用node编写git钩子hooks的示例
关于 git 钩子函数,就是在 git 进行提交的时候触发一些可执行脚本的功能,详情可以看这篇博客【GIT知识】git进阶-hooks勾子脚本_git hooks-CSDN博客,我这里稍微演示一下怎么用 node 编写钩子的脚本 以 pre-commit 钩子为例,会在用…...
RISC-V架构新生态:鸿道Intewell操作系统×全志D1芯片
在全球化技术博弈与自主可控需求的双重驱动下,RISC-V架构正从开源革命走向产业落地。然而,RISC-V生态的成熟不仅需要硬件层面的突破,更需操作系统与芯片的深度协同。鸿道Intewell操作系统与全志D1(RISC-V架构)芯片的适…...
盈达科技:重新定义GEO优化的技术边界与商业未来
——以硬核技术领跑生成式AI时代的认知主权争夺战 01 技术架构:AICC 2.0智能协同中心 生成式AI优化的「核动力引擎」 盈达科技独创的AICC 2.0(自适应-智能-认知-动态响应)智能协同中心,构建…...
芯片测试工具系统Demo示例
芯片测试工具系统Demo示例 一个简单的芯片测试工具系统Demo示例,包含基础功能和模拟测试流程,使用Python实现: python import time import random import csv from datetime import datetime class VirtualChip: """模…...
从单模态到多模态:五大模型架构演进与技术介绍
前言 1. ResNet — 残差神经网络背景核心问题与解决方案原理模型架构ResNet 系列变体技术创新与影响 2. ViT — Vision Transformer背景核心思想发展历程Transformer的起源:ViT的出现:ViT的进一步发展: 模型架构技术创新与影响 3. Swin Trans…...
基于 Java 的淘宝 API 调用实践:商品详情页 JSON 数据结构解析与重构
一、引言 在电商领域,淘宝拥有海量的商品数据。通过调用淘宝 API 可以获取商品详情页的 JSON 数据,这对于商家进行市场分析、竞品调研等具有重要意义。本文将详细介绍如何使用 Java 调用淘宝 API,获取商品详情页的 JSON 数据,并对…...
Sentinel源码—3.ProcessorSlot的执行过程二
大纲 1.NodeSelectorSlot构建资源调用树 2.LogSlot和StatisticSlot采集资源的数据 3.Sentinel监听器模式的规则对象与规则管理 4.AuthoritySlot控制黑白名单权限 5.SystemSlot根据系统保护规则进行流控 3.Sentinel监听器模式的规则对象与规则管理 (1)Sentinel的规则对象 …...
【C++11】列表初始化、右值引用、完美转发、lambda表达式
📚 博主的专栏 🐧 Linux | 🖥️ C | 📊 数据结构 | 💡C 算法 | 🌐 C 语言 上篇文章:unordered_map、unordered_set底层编写 下篇文章:C11:新的类功能、模板的可…...
Spring中IOC的重点理解(笔记)
Spring: 出现在2002左右.解决企业级开发的难度.减轻对项目模块 类与类之间的管理帮助开发人员创建对象,管理对象之间的关系. 补充:什么是OCP原则?(面试) (1)是软件七大开发当中最基本的一个原则ÿ…...
数据库系统概论|第三章:关系数据库标准语言SQL—课程笔记4
前言 前面详细介绍了关于SELECT语句的相关使用方法,继续上文的介绍,本文将继续介绍数据查询的其他相关操作,主要包括排序(ORDER BY)子句、分组(GROUP BY)子句。与此同时,介绍完单表…...
【1】CICD持续集成-docker本地搭建gitlab代码仓库社区版
一、gitlab社区版概述 GitLab社区版(Community Edition, CE)是一个开源的版本控制系统,适用于个人开发者、中小团队及大型企业。 GitLab社区版采用MIT许可证,用户可以免费使用和修改源代码。其主要功能包括代码托管、版本控制…...
Verdi工具使用心得知识笔记(一)
Verdi工具使用知识点提炼 本文来源于移知,具体文档请咨询厚台 一、基础概念 波形依赖 Verdi本身无法生成波形,需配合VCS等仿真工具生成.fsdb文件。核心功能模块 • nTrace:代码调试与追踪 • nSchema:原理图分析 • nState&…...
【25软考网工笔记】第二章 数据通信基础(4)数据编码
目录 一、曼彻斯特编码 1. 以太网 2. 题型(考试过的选择题) 1)题目解析 二、差分曼彻斯特编码 三、两种曼彻斯特编码特点 编辑 1. 双相码 2. 将时钟和数据包含在信号数据流中 3. 编码效率低 4. 数据速率是码元速率的一半 5. 应用案例 编辑 1&…...
【正点原子STM32MP257连载】第四章 ATK-DLMP257B功能测试——USB OTG测试
1)实验平台:正点原子ATK-DLMP257B开发板 2)浏览产品:https://www.alientek.com/Product_Details/135.html 3)全套实验源码手册视频下载:正点原子资料下载中心 第四章 ATK-DLMP257B功能测试——USB OTG测试…...
现代c++获取linux系统磁盘大小
现代c获取linux系统磁盘大小 前言一、命令获取系统磁盘大小二、使用c获取系统磁盘大小三、总结 前言 本文介绍一种使用c获取linux系统磁盘大小的方法 一、命令获取系统磁盘大小 在linux系统中可以使用lsblk命令显示当前系统磁盘大小,如下图所示 lsblk二、使用c获…...
tcp和udp的数据传输过程以及区别
tcp和udp的数据传输过程以及区别 目录 一、数据传输过程 1.1 UDP 数据报服务图 1.2 TCP 字节流服务图 1.3 tcp和udp的区别 1.3.1 连接特性 1.3.2 可靠性 1.3.3 数据传输形式 1.3.4 传输效率与开销 应用场景 一、数据传输过程 1.1 UDP 数据报服务图 这张图展示了 UDP 数据报服务…...
C++项目-衡码云判项目演示
衡码云判项目是什么呢?简单来说就是这是一个类似于牛客、力扣等在线OJ系统,用户在网页编写代码,点击提交后传递给后端云服务器,云服务器将用户的代码和测试用例进行合并编译,返回结果到网页。 项目最大的两个亮点&…...
C 语言中的 volatile 关键字
1、概念 volatile 是 C/C 语言中的一个类型修饰符,用于告知编译器:该变量的值可能会在程序控制流之外被意外修改(如硬件寄存器、多线程共享变量或信号处理函数等),因此编译器不应对其进行激进的优化(如缓存…...
mysql表类型查询
普通表 SELECT table_schema AS database_name,table_name FROM information_schema.tables WHERE table_schema NOT IN (information_schema, mysql, performance_schema, sys)AND table_type BASE TABLEAND table_name NOT IN (SELECT DISTINCT table_name FROM informatio…...