设计模式:适配器模式(c++实现案例)
适配器模式
适配器模式是将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。好比日本现在就只提供110V的电压,而我的电脑就需要220V的电压,那怎么办啦?适配器就是干这活的,在不兼容的东西之间搭建一座桥梁,让二者能很好的兼容在一起工作。
在软件开发中,有的时候系统的数据和行为都正确,但接口不符合,我们应该考虑使用适配器模式,目的是使控制范围之外的一个原有对象与某个接口匹配。举个例子:在开发一个模块的时候,有一个功能点实现起来比较费劲,但是,之前有一个项目的模块实现了一样的功能点;但是现在这个模块的接口和之前的那个模块的接口是不一致的。此时,作为项目经理的你,该怎么办啦?使用适配器模式,将之前实现的功能点适配进新的项目了。
适配器模式实现步骤
- 适配器实现与其中一个现有对象兼容的接口
- 现有对象可以使用该接口安全地调用适配器方法
- 适配器方法被调用后将以另一个对象兼容的格式和顺序将请求传递给该对象
参考:适配器模式 --菜鸟教程
我们有一个 MediaPlayer 接口和一个实现了 MediaPlayer 接口的实体类 AudioPlayer。默认情况下,AudioPlayer 可以播放 mp3 格式的音频文件。
我们还有另一个接口 AdvancedMediaPlayer 和实现了 AdvancedMediaPlayer 接口的实体类。该类可以播放 vlc 和 mp4 格式的文件。
我们想要让 AudioPlayer 播放其他格式的音频文件。为了实现这个功能,我们需要创建一个实现了 MediaPlayer 接口的适配器类 MediaAdapter,并使用 AdvancedMediaPlayer 对象来播放所需的格式。
AudioPlayer 使用适配器类 MediaAdapter 传递所需的音频类型,不需要知道能播放所需格式音频的实际类。AdapterPatternDemo 类使用 AudioPlayer 类来播放各种格式。
使用C++实现:
//音乐播放器
class MediaPlayer
{
public:virtual void play(string type,string name) = 0;virtual ~MediaPlayer() {};
};
//高级音乐播放类
class AdvancedMediaPlayer
{
public:virtual ~AdvancedMediaPlayer() {}virtual void playVlc(string name) = 0;virtual void playMp4(string name) = 0;
};
//支持Vlc的音乐播放器
class VlcPlayer :public AdvancedMediaPlayer
{
public:~VlcPlayer() {}void playVlc(string name)override{cout << "播放vlc类型音乐: " << name << endl;}void playMp4(string name)override {}//无需实现
};
//支持Mp4的音乐播放器
class Mp4Player :public AdvancedMediaPlayer
{
public:~Mp4Player() {}void playVlc(string name)override {}void playMp4(string name)override{cout << "播放Mp4类型音乐: " << name << endl;}
};
//接口适配器类
class MediaPlayerAdapter:public MediaPlayer
{
public:MediaPlayerAdapter(string type){if (type == "vlc"){if (pAdvance){delete pAdvance;}pAdvance = new VlcPlayer;}else if (type == "mp4"){if (pAdvance){delete pAdvance;}pAdvance = new Mp4Player;}}~MediaPlayerAdapter() { if (pAdvance!=nullptr) delete pAdvance; }void play(string type, string name)override{if (type == "vlc") pAdvance->playVlc(name);else if (type == "mp4") pAdvance->playMp4(name);}
private:AdvancedMediaPlayer* pAdvance = nullptr;
};
//整合音乐播放器
class AutioPlayer :public MediaPlayer
{
public:~AutioPlayer() { if (Mediaplayer != nullptr) delete Mediaplayer; }void play(string type, string name)override{if (type == "mp3"){cout << "播放Mp3类型音乐: " << name << endl; //内置支持mp3类型音乐}else if(type == "vlc" || type == "mp4"){if (Mediaplayer){delete Mediaplayer;}Mediaplayer = new MediaPlayerAdapter{ type };//转换适配音乐类型Mediaplayer->play(type,name); //播放音乐}else{cout << "不支持的音乐类型: " << type << endl;}}
private:MediaPlayerAdapter* Mediaplayer;
};int main()
{AutioPlayer* music = new AutioPlayer;music->play("mp3", "青花瓷 -周杰伦");music->play("mp4", "逆战 -张杰");music->play("vlc", "一人我饮酒醉");music->play("avi", "yellow");delete music;return 0;
}
优点
- 降低了去实现一个功能点的难度,可以对现有的类进行包装,就可以进行使用了
- 提高了项目质量,现有的类一般都是经过测试的,使用了适配器模式之后,不需要对旧的类进行全面的覆盖测试;
- 总的来说,提高了效率,降低了成本。
缺点
- 类适配器模式,由于多继承,可能会出现二义性
- 对象适配器模式,如果过多使用适配器模式,会导致代码阅读难度增大
相关文章:

设计模式:适配器模式(c++实现案例)
适配器模式 适配器模式是将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。好比日本现在就只提供110V的电压,而我的电脑就需要220V的电压,那怎么办啦?适配器就是干这活的࿰…...
Python|每日一练|数组|回溯|哈希表|全排列|单选记录:全排列 II|插入区间|存在重复元素
1、全排列 II(数组,回溯) 给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。 示例 1: 输入:nums [1,1,2]输出:[[1,1,2], [1,2,1], [2,1,1]] 示例 2: 输…...

Linux进程状态
Linux进程状态前言阻塞挂起Linux进程状态R运行状态S睡眠状态D磁盘休眠状态T停止状态X死亡状态Z僵尸状态僵尸进程的总结前言 在介绍Linux的进程状态之前,我们先做一个小调查: 正在运行的程序是一直在运行吗?或者说正在运行的程序一直在被cpu处…...

大数据第一轮复习笔记
linux: 添加用户 useradd 删除用户 userdel useradd -d指定组 添加组 groupadd 删除组 groupdel 创建目录 mkdir -p 删除目录 rm -rf 创建目录 touch cat -n 查看文件(显示行号)...

HTML面试题
HTML面试题部分知识点梳理 1.如何理解HTML语义化 让页面的内容结构化,便于对浏览器、引擎解析,易于阅读,便于维护理解,利于SEO。 2.H5的新特性 video/audio视频/音频canvas 绘画geolocation 定位 用于定位用户的位置WebSocket…...

CUDA内存管理一文理清|参加CUDA线上训练营
CUDA 内存概述 GPU的内存包括: 全局内存(global memory)常量内存(constant memory)纹理内存核表面内存(texture memory)寄存器(register)局部内存(local me…...

Transformation(转换算子)
分布式代码的分析 启动spark程序的代码 在yarn中启动(没有配置环境变量) /export/server/spark/bin/spark-submit --master yarn --num-executors 6 /root/helloword.py # 配置环境变量 spark-submit --master yarn --num-executors 6 /root/helloword.py RDD的五大特征 1、…...

总结如何设计一款营销低代码可视化海报平台
背景 我所在的部门负责的是活动业务,每天都有很多的营销活动,随之而来的就是大量的H5活动页面。而这些H5活动已经沉淀出了比较固定的玩法交互,我们开发大多数的工作也只是在复制粘贴这种大量的重复工作。 在基于此背景下我开始了低代码平台…...

spark04-文件读取分区数据分配原理
接 https://blog.csdn.net/oracle8090/article/details/129013345?spm1001.2014.3001.5502通过上一节知道 总字节数为7 每个分区字节数为3代码val conf: SparkConf new SparkConf().setMaster("local").setAppName("wordcount")val sc: SparkContext ne…...

常见的网络安全攻击及防御技术概述
网络安全技术涉及从物理层到业务层的各个层面,贯穿产品设计到产品上线运营的全流程。现阶段网络攻击的方式和种类也随着互联网技术的发展而不断迭代,做好网络安全防护的前提是我们要对网络攻击有充分的了解。下文将抛砖引玉对常见的网络安全攻击及防御技…...

NetSuite Balancing Segment平衡段
春节假期偷了一段时间懒,现在开始工作了。今朝谈一个偏门题目,于未知领域再下一城。说这个题目偏,就要讲讲渊源。话说在Oracle的EBS和Fusion产品中的COA领域有个功能叫做“Balancing Segment”。 问了几位Oracle老炮,也说是对第二…...

Docker 中遇到的问题
1:docker-tomcat 篇 第一天启动主机和虚拟机都可以正常访问,晚上睡觉的时候就挂起关机睡觉了,但到了第二天主机访问不了了,ping 也能ping 通,后来停掉容器,重启了虚拟机就好了,就很离谱。 这是成…...

树莓派用默认账号和密码登录不上怎么办;修改树莓派的密码
目录 一、重置树莓派的默认账号和密码 二、修改树莓派的密码 三、超级用户和普通用户的切换 一、重置树莓派的默认账号和密码 在SD卡中根目录建立文件userconf 在userconf中输入如下内容: pi:$6$/4.VdYgDm7RJ0qM1$FwXCeQgDKkqrOU3RIRuDSKpauAbBvP11msq9X58c8Q…...

【LeetCode】不同的二叉搜索树 [M](卡特兰数)
96. 不同的二叉搜索树 - 力扣(LeetCode) 一、题目 给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。 示例 1: 输入:n 3 输出&a…...

【软件相关】文献管理工具——Zotero
文章目录0 前期教程1 前言2 一些说明3 下载安装4 功能一:插入文献引用格式5 功能二:从网页下载文献pdf和题录6 功能三:数据多平台同步7 功能四:通过DOI添加条目及添加订阅8 安装xpi插件9 功能五:智能识别中英文文献10 …...

leetcode练习一:数组(二分查找、双指针、滑动窗口)
文章目录一、 数组理论基础二、 二分查找2.1 解题思路2.2 练习题2.2.1 二分查找(题704)2.2.2 搜索插入位置(题35)2.2.3 查找排序数组元素起止位置(题34)2.2.4 有效的完全平方数(题367)2.2.5 x 的平方根&…...

iPhone更新iOS 16.3出现应用卡死、闪退的问题怎么办?
在升级最新的 iOS 16.3 系统后,有些用户可能遇到了个别应用无法正常打开,卡死的异常情况。大家可以尝试通过如下方式解决问题。 1.重新启动应用: 如果应用出现卡死或闪退,可从 iPhone 屏幕由底往上滑(或连续按两次 H…...

TCP协议原理一
文章目录一、TCP协议二、TCP工作机制1.确认应答2.超时重传3.连接管理三次握手四次挥手一、TCP协议 我们的TCP协议相比于UDP协议复杂不少,今天我们就来一起学习一下TCP协议报文和原理 首先我们报头第一行里的端口号和UDP的端口号是一致的,都是用两个字节…...

【黑马SpringCloud(6)】Sentinel解决雪崩问题
微服务保护雪崩问题服务保护技术Sentinel微服务整合Sentinel流量控制簇点链路入门练习流控模式关联链路流控效果Warm Up排队等待热点参数限流隔离和降级FeignClient整合Sentinel线程隔离(舱壁模式)实现线程隔离熔断降级慢调用异常比例/异常数授权规则获取origin给网关添加请求头…...

微信小程序 java springboot招聘求职应聘简历系统
应聘系统是基于微信小程序,java编程语言,mysql数据库,springboot框架,idea工具开发,本系统主要分为用户,企业,管理员三个角色,用户注册登陆小程序,查看应聘分类ÿ…...

python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...

华硕a豆14 Air香氛版,美学与科技的馨香融合
在快节奏的现代生活中,我们渴望一个能激发创想、愉悦感官的工作与生活伙伴,它不仅是冰冷的科技工具,更能触动我们内心深处的细腻情感。正是在这样的期许下,华硕a豆14 Air香氛版翩然而至,它以一种前所未有的方式&#x…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...

招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
C#中的CLR属性、依赖属性与附加属性
CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...

Razor编程中@Html的方法使用大全
文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...