14.适配器模式(Adapter Pattern)
定义
适配器模式(Adapter Pattern) 是一种结构型设计模式,它允许将一个类的接口转换成客户端所期望的另一种接口。适配器模式通常用于将已有的类或遗留系统中的接口与新系统或目标接口进行兼容,从而能够在系统中无缝地使用不兼容的类。
特性
- 接口转换:适配器模式通过转换接口,使得不兼容的接口可以一起工作。
- 包装现有对象:适配器模式不修改现有对象的代码,而是通过创建适配器类来“包装”现有对象,使其符合目标接口的要求。
适用场景
适配器模式适用于以下场景:
- 接口不兼容:当你需要使用一个已有的类或系统,但它的接口不符合你的需求时,可以通过适配器模式来转换接口。
- 遗留系统:如果有一个遗留系统,它的接口无法直接与新的系统兼容,适配器可以帮助使遗留系统与新系统一起工作。
- 第三方库:如果集成了第三方库,并且库的接口与系统不兼容,可以通过适配器模式将库的接口适配成需要的接口。
类设计
适配器模式通常包括以下几个角色:
1.Target(目标接口):定义客户端所需要的接口,通常是期望的接口。
2.Adaptee(遗留接口):需要被适配的现有接口,通常是与目标接口不兼容的接口。
3.Adapter(适配器):将 Adaptee 接口转换成 Target 接口的类,可以通过继承或组合实现。
4.Client(客户端):使用 Target 接口的对象,客户端通过 Target 接口与适配器进行交互。
代码实现解析
我们通过一个简单的例子来演示适配器模式。在这个例子中,我们有一个 旧的接口 IAdaptee 和一个 新的接口 ITarget,并且需要使用一个适配器来使客户端可以通过新的接口使用旧的接口。
优点
- 促进了类之间的协同工作,即使它们没有直接的关联。
- 提高了类的复用性。
- 增加了类的透明度。
- 提供了良好的灵活性。
缺点
- 过度使用适配器可能导致系统结构混乱,难以理解和维护。
1. 定义目标接口(新接口)
class ITarget {
public:virtual void process() = 0; // 新接口方法
};ITarget 是客户端期望的接口,process() 方法是客户端需要调用的方法。
2. 定义遗留接口(老接口)
class IAdaptee {
public:virtual void foo(int data) = 0; // 老接口方法virtual int bar() = 0; // 老接口方法
};
IAdaptee 是遗留的接口,里面有两个方法:foo() 和 bar(),这些方法是旧系统或类提供的接口。
3. 旧类实现遗留接口
class OldClass : public IAdaptee {
public:void foo(int data) override {// 实际业务逻辑cout << "OldClass::foo(" << data << ")" << endl;}int bar() override {// 实际业务逻辑cout << "OldClass::bar()" << endl;return 42; // 返回示例数据}
};
OldClass 是实现了 IAdaptee 接口的类,它的接口与客户端所期望的接口不兼容。
4. 适配器实现(对象适配器)
class Adapter : public ITarget {
protected:IAdaptee* pAdaptee; // 组合旧接口的实例public:Adapter(IAdaptee* pAdaptee) : pAdaptee(pAdaptee) {}void process() override {// 将新接口的调用转发给旧接口的调用int data = pAdaptee->bar(); // 调用旧接口的 bar()pAdaptee->foo(data); // 调用旧接口的 foo()}
};对象适配器:在这个实现中,Adapter 类继承了 ITarget 接口,并持有 IAdaptee 的实例。
它将 process() 方法的调用转发到旧接口的 bar() 和 foo() 方法。组合方式:适配器类通过组合方式引用旧接口类,而不是继承。
5. 客户端调用
int main() {IAdaptee* pAdaptee = new OldClass(); // 创建旧接口对象ITarget* pTarget = new Adapter(pAdaptee); // 创建适配器对象// 客户端通过适配器调用新接口pTarget->process(); // 调用适配器的 process(),内部会调用旧接口的方法delete pAdaptee;delete pTarget;return 0;
}
客户端通过 Adapter 来访问 OldClass,而不需要直接与 OldClass 交互。
客户端只与 ITarget 接口交互。
6. 类适配器实现
适配器也可以通过 多继承 实现,这称为 类适配器。通过继承旧接口,适配器类可以同时继承目标接口和遗留接口。
class Adapter : public ITarget, protected OldClass { // 多继承
public:void process() override {int data = bar(); // 直接调用旧接口的方法foo(data); // 直接调用旧接口的方法}
};
类适配器:在类适配器中,Adapter 类继承了 OldClass,
它不仅实现了 ITarget 接口,而且还继承了 OldClass,可以直接调用 OldClass 的方法。
完整代码:
//目标接口(新接口)
class ITarget{
public:virtual void process()=0;
};//遗留接口(老接口)
class IAdaptee{
public:virtual void foo(int data)=0;virtual int bar()=0;
};//遗留类型
class OldClass: public IAdaptee{//....
};//对象适配器
class Adapter: public ITarget{ //继承
protected:IAdaptee* pAdaptee;//组合public:Adapter(IAdaptee* pAdaptee){this->pAdaptee=pAdaptee;}virtual void process(){int data=pAdaptee->bar();pAdaptee->foo(data);}};//类适配器
class Adapter: public ITarget,protected OldClass{ //多继承}int main(){IAdaptee* pAdaptee=new OldClass();ITarget* pTarget=new Adapter(pAdaptee);pTarget->process();}class stack{deqeue container;};class queue{deqeue container;};
总结
Adapter 模式的优点:
- 解耦:客户端与旧接口解耦,客户端通过目标接口与适配器交互,不直接与遗留系统进行交互。
- 复用:适配器模式可以使旧系统或类重用,而不需要修改旧代码。
- 适应性强:代理类可以灵活适应不同的接口需求,尤其在接口不兼容时尤为有用。
Adapter 模式的缺点:
- 增加类的数量:引入适配器类增加了系统的复杂度和类的数量,可能导致代码维护复杂度增加。
- 性能开销:适配器可能会引入额外的性能开销,尤其是当有多个适配器时。
适用场景:
- 接口不兼容的类:当现有类的接口与目标接口不兼容时,使用适配器模式可以将接口转换成目标接口,确保客户端可以正常使用。
- 遗留系统的集成:将遗留系统与新系统进行集成时,适配器模式可以帮助适配旧系统的接口。
- 第三方库集成:在使用第三方库时,如果库的接口与系统不兼容,适配器模式可以将库的接口适配成系统需要的接口。
总结
适配器模式通过提供一个代理类来将不兼容的接口转换成客户端需要的接口,确保了客户端与系统之间的解耦。通过适配器,客户端可以在不修改现有系统代码的前提下,使用不兼容的类或接口。
相关文章:
14.适配器模式(Adapter Pattern)
定义 适配器模式(Adapter Pattern) 是一种结构型设计模式,它允许将一个类的接口转换成客户端所期望的另一种接口。适配器模式通常用于将已有的类或遗留系统中的接口与新系统或目标接口进行兼容,从而能够在系统中无缝地使用不兼容…...
Crewai框架配置回调函数
官方文档里只指提了一句 不过不太难,在crew.py文件里配置一下就行了,下面是一个demo,这个函数会在research_task任务执行完触发(配置LLM这里请看我这篇博客) from crewai import Crew, Process, Agent, Taskfrom src.…...
大数据方向知识图谱及发展前景分析
目录 一、知识体系 二、大数据领域前景分析: 1. 市场需求 2. 技术趋势 3. 职业发展路径 4. 学习路线建议 5. 推荐认证体系 一、知识体系 大数据知识体系 ├── 基础理论 │ ├── 数学基础:概率统计、线性代数、离散数学 │ ├── 计算机基…...
Playwright 与 Selenium 的关系
Playwright 与 Selenium 的关系 Playwright 和 Selenium 都是流行的浏览器自动化测试工具,它们都可以用于 Web 应用的端到端测试,但它们在设计理念、架构和功能上存在一些差异。 以下是两者的主要关系对比: 特性PlaywrightSelenium开发语言…...
拧紧“安全阀”,AORO-P300 Ultra防爆平板畅通新型工业化通信“大动脉”
在油气管道泄漏的浓烟中,在矿道坍塌的密闭空间里,在洪水肆虐的救援现场,传统通讯设备频频失效的困境已成为历史。AORO-P300 Ultra防爆平板集5G通讯、红外感知、应急照明等实用功能于一体,以军工级防护与全场景智能应用,…...
《C#之集训1-20121019c#基础》
 C#是微软公司发布的一种面向对象的、运行于.NET Framework之上的高级程序设计语言。它是微软公司研究员Anders Hejlsberg的最新成果。 C#曾经的它在我眼中是很高大上的,一直没有目睹其风采,现在终于揭开了它神秘的面纱…...
基于docker搭建Kafka集群,使用KRaft方式搭建,摒弃Zookeeper
KAFKA基于docker使用KRaft进行集群搭建 环境:已成功搭建kafka服务 可点击链接跳转至安装kafka-3.8.0版本 并启用SASL认证 教程 使用基于Zookeeper方式搭建集群教程 kafka-3.8.0版本 并启用SASL认证 教程 搭建kafka-ui可视化工具 192.168.2.91 192.168.2.92 192…...
CAD导入与解析,助力工业数据可视化高效呈现
背景 在企业的日常设计与管理中,CAD图纸早已成为不可或缺的重要资产,多年来知识积累的载体,凝聚了大量的心血与智慧。然而,CAD图纸往往只作为静态文件保存,应用场景较为有限。在数字经济时代,如何让CAD图纸…...
基于docker部署kafka-3.8.0版本,并开启SASL认证模式
1、下载安装包 (1)https://kafka.apache.org/downloads 下载如下图版本 2、解压安装包 执行tar -xvf kafka_2.13-3.8.0.tgz命令对安装包进行解压。 3、增加配置文件 (1)进入 /kafka_2.13-3.8.0/config 目录 (2&a…...
从零开始人工智能Matlab案例-KNN的二维数据分类
基于K最近邻(K-Nearest Neighbors, KNN)算法的二分类案例,包含完整MATLAB代码、算法原理和核心思想说明。此案例使用合成数据集,无需复杂数据预处理,适合快速理解。 案例:基于KNN的二维数据分类 目标&…...
90.子集||
要求所有可能的子集,不能重复,因此对于相同的数字,要考虑去重,去重的方式就是通过排序,排序后相同的数字相邻,这样进行实现迭代时,若没有选择上一个数,,其当前数字与上一…...
4 HBase 的高级 shell 管理命令
4 HBase 的高级 shell 管理命令 1.status 例如:显示服务器状态 hbase(main):058:0> status node012.whoami 显示 HBase 当前用户,例如: hbase> whoami3.list 显示当前所有的表 hbase> list4.count 统计指定表的记录数,…...
Spring AOP 扫盲
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/literature?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,…...
DeepSeek 提示词之角色扮演的使用技巧
老六哥的小提示:我们可能不会被AI轻易淘汰,但是会被“会使用AI的人”淘汰。 在DeepSeek的官方提示库中,有“角色扮演(自定义人设)”的提示词案例。截图如下: 在“角色扮演”的提示词案例中,其实…...
python3中错误与异常初识
一. 简介 在 编写 Python时,经常会遇到一些报错信息。接下来开始学习 Python3 中错误和异常。 本文首先初步了解一下 Python3中的错误和异常。 二. python3 中错误与异常初识 Python 中有两种错误:语法错误与异常。 1. 语法错误 Python 的语法错误…...
设计模式六大原则和单例模式
设计模式 目的 实现可重用解决方案,构筑易维护、可扩展的软件系统。 六大原则 单一职责: 类的职责单一,一个方法做一件事。 开闭原则: 拓展开放,修改关闭。 里氏替换: 父类能出现的地方,子…...
【图像处理】- 基本图像操作
基本图像操作详解 基本图像操作是图像处理的基础,涵盖了对图像进行简单但重要的变换。以下是几种常见的基本图像操作及其详细说明: 1. 裁剪 (Cropping) 描述:从原始图像中提取一个矩形区域。 实现方法: 使用图像的坐标系指定…...
Attention is All You Need-Transformer模型论文精读+架构分析--简单易懂版
Foreword写在前面的话: 大家好,我是一名刚开始学习Transformer的新手。这篇文章是我在学习Transformer过程中的一些笔记和心得,希望能和同样在学习人工智能深度学习模型的朋友们分享。由于我的知识有限,文章中可能存在错误或不准确…...
Qt跨屏窗口的一个Bug及解决方案
如果我们希望一个窗口覆盖用户的整个桌面,此时就要考虑用户有多个屏幕的场景(此窗口要横跨多个屏幕),由于每个屏幕的分辨率和缩放比例可能是不同的,Qt底层在为此窗口设置缩放比例(DevicePixelRatio…...
Spark--算子执行原理
一、sortByKey SortByKey是一个transformation算子,但是会触发action,因为在sortByKey方法内部,会对每个分区进行采样,构建分区规则(RangePartitioner)。 内部执行流程 1、创建RangePartitioner part&…...
javaEE-6.网络原理-http
目录 什么是http? http的工作原理: 抓包工具 fiddler的使用 HTTP请求数据: 1.首行:编辑 2.请求头(header) 3.空行: 4.正文(body) HTTP响应数据 1.首行:编辑 2.响应头 3.空行: 4.响应正文…...
基于 docker 的mysql 5.7 主主集群搭建
创建挂载目录和配置文件 主节点1 mkdir -p /mysql_master_1/mysql/log mkdir -p /mysql_master_1/mysql/data mkdir -p /mysql_master_1/mysql/conf vim /mysql_master_1/mysql/conf/my.cnf[mysqld] datadir/var/lib/mysql #MySQL 数据库文件存放路径 server_id 1 #指定数据…...
windows版的docker如何使用宿主机的GPU
windows版的docker使用宿主机的GPU的命令 命令如下 docker run -it --nethost --gpus all --name 容器名 -e NVIDIA_DRIVER_CAPABILITIEScompute,utility -e NVIDIA_VISIBLE_DEVICESall 镜像名效果 (transformer) rootdocker-desktop:/# python Python 3.9.0 (default, Nov 15 …...
【C++】STL——list的使用
目录 💕1.带头双向链表List 💕2.list用法介绍 💕3.list的初始化 💕4.size函数与resize函数 💕5.empty函数 💕6.front函数与back函数 💕7.push_front,push_back,pop_front,pop_back函数…...
6.PPT:魏女士-高新技术企业政策【19】
目录 NO1234 NO567 NO1234 创建“PPT.pptx”考生文件夹Word素材文档:选中对应颜色的文字→选中对应的样式单击右键按下匹配对应文字:应用所有对应颜色的文字开始→创建新的幻灯片→从大纲:考生文件夹:Word素材重置 开始→版…...
MLA 架构
注:本文为 “MLA 架构” 相关文章合辑。 未整理去重。 DeepSeek 的 MLA 架构 原创 老彭坚持 产品经理修炼之道 2025 年 01 月 28 日 10:15 江西 DeepSeek 的 MLA(Multi-head Latent Attention,多头潜在注意力)架构 是一种优化…...
文本分析NLP的常用工具和特点
1)非上下文感知型文本分析工具和特点 特性VADERTextBlob适合文本类型短文本、非正式语言(如评论、推文)中等长度、正式文本情感强度分析支持(正面、负面、中性)支持(极行、主观性)处理表情符号…...
AI协助探索AI新构型自动化创新的技术实现
一、AI自进化架构的核心范式 1. 元代码生成与模块化重构 - 代码级自编程:基于神经架构搜索的强化学习框架,AI可通过生成元代码模板(框架的抽象层定义、神经元结点-网络拓扑态的编码抽象定义)自动组合功能模块。例如࿰…...
7.抽象工厂(Abstract Factory)
抽象工厂与工厂方法极其类似,都是绕开new的,但是有些许不同。 动机 在软件系统中,经常面临着“一系列相互依赖的对象”的创建工作;同时,由于需求的变化,往往存在更多系列对象的创建工作。 假设案例 假设…...
Android-音频采集
前言 音视频这块,首先是要先采集音频。今天我们就来深入探讨一下 Android 音频采集的两大类型:Mic 音频采集和系统音频采集。 Mic音频采集 Android提供了两个API用于实现录音功能:android.media.AudioRecord、android.media.MediaRecorder。…...
