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

C++设计模式——Adapter适配器模式

一,适配器模式简介

适配器模式是一种结构型设计模式,用于将已有接口转换为调用者所期望的另一种接口。

适配器模式让特定的API接口可以适配多种场景。例如,现有一个名为"Reader()"的API接口只能解析txt格式的文件,给这个Reader()接口增加适配器以后,它可以同时支持xml、json、csv等格式的文件。

适配器是一个特殊的类,它可以扩展或者说转接一些特定API接口的功能,使得API接口可以被应用到更多对象或数据类型上。

适配器会将适配过程进行封装,从而隐藏适配的过程,只对外界提供被适配以后的API接口。

适配器在真实世界中的模拟:

1.USB转接头,实现typec接口转USB。

2.设备网关,让ipv4网络与ipv6网络互通。

适配器模式的主要组件:

1.目标接口(Target):提供给外部程序的统一接口,是外部调用者(client)期望使用的接口。

2.源接口(Adaptee):已经具备一定的功能,但是与Target不兼容的接口。它包含了client所需要的功能,但是不能被client所使用。

3.适配器(Adapter):对源接口进行适配,使得源接口可以像目标接口一样被公共调用。适配器提供了Target的接口实现,并通过继承或组合的方式调用了Adaptee的接口。

适配器模式的优点:

1.可以实现对现有组件代码的复用。

2.使得不兼容的组件之间可以成功交互。

3.降低了各种接口之间的用法差异。

4.方便集成第三方库或者API。

适配器模式与桥接模式(Bridge Pattern)的区别:

两者的用途不同,桥接模式的用途是将接口与实现分开,适配器模式的用途是修改现有接口,从而解决兼容问题。

二,适配器模式的应用场景

在开发场景中,适配器模式的应用场景有:

1.兼容相同业务下的不同接口实现。

2.兼容不同的通信方式,比如使用适配器将UDP通信转为内部的共享内存通信。

3.处理代码中不同类之间交互时的兼容问题。

在嵌入式开发场景,经常使用的Wrapper,也是一种适配器模式。Wrapper是指将传感器等硬件或者操作系统的底层API封装成一种高级接口或者类,从而提供给上层应用去调用。

Wrapper可以隐藏底层的具体实现细节,使上层应用程序可以更加方便地使用底层接口。例如,当嵌入式设备需要读写摄像头数据时,我们可以把摄像头提供的SDK封装成一个Wrapper,从而简化了调用方式。

不推荐使用适配器的场景:

1.原有接口的变动很大的时候。

2.对接口性能要求很高的时候。

3.适配器需要适配的地方过多的时候。

三,适配器代码样例

1.UML类图

Adapter类继承了Target类并重写了Target类的request接口,Adapter类实现request接口的时候调用了Adaptee类提供的specificRequest接口。

整体上,相当于Adapter类为Adaptee类的specificRequest接口做了适配。

2.代码实现

#include <iostream>
//目标接口
class Target
{
public:virtual void request() = 0;
};
//源接口
class Adaptee
{
public:void specificRequest(){std::cout << "Adaptee specific request" << std::endl;}
};
//被适配后的源接口
class Adapter : public Target
{
public:Adapter(Adaptee* adaptee) : m_adaptee(adaptee) {}void request() override{m_adaptee->specificRequest();}
private:Adaptee* m_adaptee;
};
int main()
{Adaptee* adaptee = new Adaptee();Target* target = new Adapter(adaptee);target->request();return 0;
}

运行结果: 

Adaptee specific request

四,适配器模式的分类

1.类适配器:

类适配器以类继承的方式适配不兼容的源接口。

C++语法支持继承自多个父类(钻石继承),适配器同时继承了目标接口和源接口,从而使得源接口的函数可以被目标接口所调用。

2.对象适配器:

对象适配器以对象组合的方式适配不兼容的源接口。所谓的对象组合,是指在一个对象内部调用另一个对象的成员函数。

对象适配器中包含了源接口的实例对象,对象适配器的可扩展性更好,方便加入新的功能进行适配。

五,代码实战

Demo1:  

适配了咖啡机和榨汁机的饮料机,采用对象适配器实现。

#include <iostream>
#include <functional>class  Beverage {
public:virtual void getBeverage() = 0;
};class CoffeeMaker {
public:CoffeeMaker() = default;void Brew() {std::cout << "Brewing coffee" << std::endl;}
};class JuiceMaker {
public:JuiceMaker() = default;void Squeeze() {std::cout << "Squeezeing Juice" << std::endl;}
};class Adapter : Beverage {  
private:std::function<void()> m_request;
public:Adapter(CoffeeMaker* cm){ m_request = [cm]() { cm->Brew(); };}Adapter(JuiceMaker* jm) { m_request = [jm]() { jm->Squeeze(); }; }//对外公共接口void getBeverage() { m_request(); }
};int main() {CoffeeMaker* CM= new CoffeeMaker();Adapter coffee(CM);coffee.getBeverage();JuiceMaker* JM = new JuiceMaker();Adapter juice(JM);juice.getBeverage();return 0;
}

运行结果: 

Brewing coffee
Squeezeing Juice

Demo2: 

类适配器与对象适配器代码对比

#include <iostream>//目标接口
class Target {
public:virtual void Request() = 0;
};//源接口
class Adaptee {
public:void SpecificRequest() {std::cout << "Adaptee output." << std::endl;}
};//对象适配器
class ObjectAdapter : public Target {
public://源接口的实例化ObjectAdapter(Adaptee* adaptee) : m_adaptee(adaptee) {}void Request() override {std::cout << "From ObjectAdapter: ";m_adaptee->SpecificRequest();}
private:Adaptee* m_adaptee;
};//类适配器
//钻石继承
class ClassAdapter : public Target, private Adaptee {
public:void Request() override {std::cout << "From ClassAdapter: " ;SpecificRequest();}
};int main()
{Adaptee* adaptee = new Adaptee();ObjectAdapter* adapter_1 = new ObjectAdapter(adaptee);ClassAdapter* adapter_2 = new ClassAdapter();adapter_1->Request();adapter_2->Request();return 0;
}

运行结果:

From ObjectAdapter: Adaptee output.
From ClassAdapter: Adaptee output.

六,参考阅读

https://refactoring.guru/design-patterns/adapter

https://www.geeksforgeeks.org/adapter-pattern-c-design-patterns/

相关文章:

C++设计模式——Adapter适配器模式

一&#xff0c;适配器模式简介 适配器模式是一种结构型设计模式&#xff0c;用于将已有接口转换为调用者所期望的另一种接口。 适配器模式让特定的API接口可以适配多种场景。例如&#xff0c;现有一个名为"Reader()"的API接口只能解析txt格式的文件&#xff0c;给这…...

Python文本处理利器:jieba库全解析

文章目录 Python文本处理利器&#xff1a;jieba库全解析第一部分&#xff1a;背景和功能介绍第二部分&#xff1a;库的概述第三部分&#xff1a;安装方法第四部分&#xff1a;常用库函数介绍1. 精确模式分词2. 全模式分词3. 搜索引擎模式分词4. 添加自定义词典5. 关键词提取 第…...

【C/C++】C语言如何实现类似C++的智能指针?

在C中&#xff0c;智能指针是为了自动化资源管理而引入的工具。比如std::unique_ptr和std::shared_ptr等&#xff0c;它们管理着所持有对象的生命周期&#xff0c;可以在智能指针被销毁时自动释放其所持有的资源。在C语言中&#xff0c;虽然没有直接的智能指针概念&#xff0c;…...

九大微服务监控工具详解

Prometheus Prometheus 是一个开源的系统监控、和报警工具包&#xff0c;Prometheus 被设计用来监控“微服务架构”。 主要解决&#xff1a; 监控和告警&#xff1a;Prometheus 可以对系统、和应用程序进行实时监控&#xff0c;并在出现问题时发送告警&#xff1b;数据收集和…...

java aliyun oss上传和下载工具类

java aliyun oss上传和下载工具类 依赖 <dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.8.0</version></dependency>工具类 import com.alibaba.fastjson.JSON; import c…...

P7 品牌管理

逆向生成页面 新增菜单—商品系统的品牌管理 —product/brand 在代码生成器得到的文件中&#xff0c; main-resources-src-views-modules-product brand.vue、brand-add-or-update.vue放到category.vue同级vue文件有新增、删除按钮&#xff0c;但页面未显示&#xff0c;是因…...

C语言详解(动态内存管理)1

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f4a5;&#x1f4a5;个人主页&#xff1a;奋斗的小羊 &#x1f4a5;&#x1f4a5;所属专栏&#xff1a;C语言 &#x1f680;本系列文章为个人学习…...

106.网络游戏逆向分析与漏洞攻防-装备系统数据分析-在UI中显示装备与技能信息

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 如果看不懂、不知道现在做的什么&#xff0c;那就跟着做完看效果&#xff0c;代码看不懂是正常的&#xff0c;只要会抄就行&#xff0c;抄着抄着就能懂了 内容…...

AWS EMR Serverless

AWS概述 EMR Serverless 简介 在AWS概述一文中简单介绍过AWS EMR, 它是AWS提供的云端大数据平台。借助EMR可以设置集群以便在几分钟内使用大数据框架处理和分析数据。创建集群可参考官方文档&#xff1a;Amazon EMR 入门。但集群创建之后需要一直运行&#xff0c;用户需要管理…...

Java面试题:Redis持久化问题

Redis持久化问题 RDB (Redis Database Backup File) Redis数据快照 将内存中的所有数据都记录到磁盘中做快照 当Redis实例故障重启时,从磁盘读取快照文件恢复数据 使用 save/bgsave命令进行手动快照 save使用主进程执行RDB,对所有命令都进行阻塞 bgsave使用子进程执行R…...

【Java】解决Java报错:ClassCastException

文章目录 引言1. 错误详解2. 常见的出错场景2.1 错误的类型转换2.2 泛型集合中的类型转换2.3 自定义类和接口转换 3. 解决方案3.1 使用 instanceof 检查类型3.2 使用泛型3.3 避免不必要的类型转换 4. 预防措施4.1 使用泛型和注解4.2 编写防御性代码4.3 使用注解和检查工具 5. 示…...

OpenCV-最小外接圆cv::minEnclosingCircle

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 函数原型 void minEnclosingCircle(InputArray points, Point2f& center, float& radius); 参数说明 InputArray类型的…...

大小堆运用巧解数据流的中位数

​​​​​​​​​​ 一、思路 我们将所有数据平分成两份&#xff0c;前面那一部分用小堆来存&#xff0c;后面的部分用大堆来存&#xff0c;这样我们就能立刻拿到中间位置的值。 如果是奇数个数字&#xff0c;那么我们就将把中间值放在前面的大堆里&#xff0c;所以会有两种…...

AI能力边界不断扩展,将对国家安全产生深远影响

文 | 中国信息安全测评中心 王欣 随着 ChatGPT 的发布及相关应用的落地&#xff0c;人工智能技术给全球各个行业带来了一波又一波冲击。GPT-4 多模态大型语言模型更是将人工智能的能力提升到新的高度&#xff0c;无论从技术先进性还是应用实践能力来看&#xff0c;此模型均可被…...

【UnityShader入门精要学习笔记】第十六章 Unity中的渲染优化技术 (上)

本系列为作者学习UnityShader入门精要而作的笔记&#xff0c;内容将包括&#xff1a; 书本中句子照抄 个人批注项目源码一堆新手会犯的错误潜在的太监断更&#xff0c;有始无终 我的GitHub仓库 总之适用于同样开始学习Shader的同学们进行有取舍的参考。 文章目录 移动平台上…...

GPT-4o:免费且更快的模型

OpenAI GPT-4o 公告 OpenAI 推出了增强版 GPT-4 模型——OpenAI GPT-4o&#xff0c;用于支持 ChatGPT。首席技术官 Mira Murati 表示&#xff0c;更新后的模型速度更快&#xff0c;并在文本、视觉和音频处理方面有了显著提升。GPT-4o 将免费向所有用户开放&#xff0c;付费用户…...

docker部署fastdfs

我的镜像包地址 链接&#xff1a;https://pan.baidu.com/s/1j5E5O1xdyQVfJhsOevXvYg?pwdhcav 提取码&#xff1a;hcav docker load -i gofast.tar.gz拉取gofast docker pull sjqzhang/go-fastdfs启动gofast docker run -d --name fastdfs -p 8080:8080 -v /opt/lijia/lijia…...

【劲舞团game】

编写《劲舞团》这样的游戏代码是一个复杂的过程&#xff0c;涉及到游戏引擎的使用、图形渲染、物理模拟、音频处理、网络通信等多个方面。以下是一个非常简化的步骤&#xff0c;用于说明如何开始编写一个基于Unity引擎的简单舞蹈游戏&#xff1a; 1. 准备开发环境 下载并安装…...

Day15—图像爬虫与简单处理

图像爬虫是一种专门用于从互联网上下载图像的网络爬虫。除了文本内容,图像也是网站中的重要组成部分,它们可以用于多种目的,如图像识别、内容分析、数据备份等。 环境准备 首先,确保你的环境中已安装Python和必要的库。如果没有安装Pillow库,可以通过以下命令安装:pip in…...

Rust基础学习-Rust中的文件操作

文件结构 在Rust中&#xff0c;std::fs::File 结构体代表一个文件。它允许我们对文件执行读/写操作。文件 I/O 是通过提供与文件系统交互的功能的 std::fs 模块执行的。 File 结构体中的所有方法都返回std::io::Result的变体&#xff0c;或者简单地是 Result 枚举。这里会涉及…...

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…...

Vue记事本应用实现教程

文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展&#xff1a;显示创建时间8. 功能扩展&#xff1a;记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行

项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战&#xff0c;克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...

GitFlow 工作模式(详解)

今天再学项目的过程中遇到使用gitflow模式管理代码&#xff0c;因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存&#xff0c;无论是github还是gittee&#xff0c;都是一种基于git去保存代码的形式&#xff0c;这样保存代码…...

华为OD机考-机房布局

import java.util.*;public class DemoTest5 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseSystem.out.println(solve(in.nextLine()));}}priv…...

NPOI操作EXCEL文件 ——CAD C# 二次开发

缺点:dll.版本容易加载错误。CAD加载插件时&#xff0c;没有加载所有类库。插件运行过程中用到某个类库&#xff0c;会从CAD的安装目录找&#xff0c;找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库&#xff0c;就用插件程序加载进…...

windows系统MySQL安装文档

概览&#xff1a;本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容&#xff0c;为学习者提供全面的操作指导。关键要点包括&#xff1a; 解压 &#xff1a;下载完成后解压压缩包&#xff0c;得到MySQL 8.…...