设计模式学习[15]---适配器模式

news2025/1/7 21:14:28

文章目录

  • 前言
  • 1.引例
  • 2.适配器模式
    • 2.1 对象适配器
    • 2.2 类适配器
  • 总结

前言

这个模式其实在日常生活中有点常见,比如我们的手机取消了 3.5 m m 3.5mm 3.5mm的接口,只留下了一个 T y p e − C Type-C TypeC的接口,但是我现在有一个 3.5 m m 3.5mm 3.5mm的耳机接口,那怎么让耳机和手机相连?

当然是买个转接头或者转接线,一头是 3.5 m m 3.5mm 3.5mm圆孔一头是 t y p e − c type-c typec接口。
那这里的转接头或者转接线,充当的就是适配器。我手机只有type-c的接口,现在要让 3.5 m m 3.5mm 3.5mm的插头适配 t y p e − c type-c typec,就需要这个适配器。

这篇博客就写一下适配器模式,看看在软件开发里面,什么时候用适配器,又是怎么用的适配器。

1.引例

我们日常写代码,一般都在debug版本下写,调试程序也是这样。但是我们要发布程序的时候,肯定是要release版本发布的。发布给客户的软件出现了bug,崩溃了,如何快速定位?这又不是我们VS里面一个F5开始调试就能搞定的,这时候就需要根据日志文件来判断了,说到这,其实就我近期开发的模块,日志量确实不太够,惭愧。

写日志我们通常是把他写到一个log.txt这样的文件里面去,现在定义这样的一个写日志文件操作的类
在这里插入图片描述

对于这个日志类,我们在main函数中一般可以这样用:

LogToFile* plog=new LogToFile();
plog->initfile();
plog->writetofile("向日志文件中写入一条日志");
plog->readfromfile();
plog->closefile();
delete plog;

如果程序运行很久,日志越来越多,各种模块的日志信息都往这个文件添加,就会导致日志文件过大,这时候需要将日志写到文件变成写到数据库。对于这种情况,其实就是新的设计与实现,具体类如下:
在这里插入图片描述

对于这个日志写到数据库的类,我们在main函数中一般可以这样用:

LogToDatabase* plog=new LogToDatabase();
plog->initdb();
plog->writetodb("向日志文件中写入一条日志");
plog->readfromdb();
plog->closedb();
delete plog;

上面是写日志的两种方式,我们可以看到他们的实现很不一样,一个对文件操作,一个对数据库操作。

现在考虑这种情况,数据库在某一天突然G了,可能因为网络问题导致无法和数据库连接。那上面的第二种写日志的方式似乎就用不了了,我们还得用回第一种方式,但这时候又来问题了。我们目前使用的方案是数据库方案,代码都是基于LogToDatabase类的接口,而LogToDatabase类的接口和LogToFile类又不一样,咋办?

这个就相当于我们耳机一直是用type-c连手机,突然有一天手机type-c口坏了,蓝牙坏了,我们只能用有线3.5mm接口耳机,这时候咋办?转接头呀!


2.适配器模式

在不改变老日志系统源码的情况下,通过引入适配器,将使用新日志系统的项目与老日志系统接驳起来,此时,适配器扮演一个中间人的角色,将项目中针对新日志系统的接口调用转换成对应的老日志系统的接口调用,从而达到新接口适配老接口的目的,这就是适配器模式的工作

在这里插入图片描述
在这里插入图片描述

接下来是考虑适配的实现方式了,这里适配器的实现分为两种:对象适配器类适配器

前者是通过类与类之间的组合关系,也就是一个类的定义中含有其他类型的成员变量。这种关系实现了委托机制,即成员函数把功能的实现委托给了其他类的成员函数,当然需要持有一个其他类的指针,才可以实现委托。

后者则是通过类与类之间的继承关系来实现接口的适配,适配器类和和适配者类之间是继承关系。


2.1 对象适配器

在适配器模式中,一般分为三种角色

Target(目标抽象型):该类定义所需要暴露的接口,这些接口就是调用者希望使用的接口,也就是客户端需要用到的接口。这里是指LogToDatabase类。

Adaptee(适配者类):这个类表示的是被适配的角色,通常是指老接口。需要用被适配。这里是指LogToFile类。

Adapter(适配器类):这个就是适配器了,充当转换器的作用,是适配模式的核心。这里的作用就是把客户端针对LogToDatabase类的接口调用转换成对LogToFile(旧接口)的调用。

参考一下UML类图,在对象适配器中,我们需要让适配器继承目标抽象型LogToDatabase,因为它是对外暴露的接口。
其次,适配器需要有老接口类的指针,用来调用老接口。
在这里插入图片描述

现在具体看一下代码:

在这里插入图片描述

在这个类中,我们通过在适配器类LogAdapter中定义一个LogToFile的指针,在外层暴露的initdb,writetodb等接口中,调用老的接口。这样就做到了接口的适配,用同一套对外暴露的接口,实现底层的适配。

适配器模式与装饰模式有类似的地方,两者都使用了类与类之间的组合关系,但两者的实现意图是不同的,适配器模式是将原有的接口适配成另外一个接口,而装饰模式是对原有功能的增强,而且无论装饰多少层,装饰模式的调用接口始终不发生改变。

2.2 类适配器

先看UML,这里适配器类内部不再持有旧接口的指针,而也是用继承关系来做。
在这里插入图片描述

依照UML,我们的具体代码如下:

在这里插入图片描述

这里我们对于目标类LogToDatabase使用的是公有继承,对于旧接口LogToFile类,我们使用的是私有继承。
这里public继承表示的时一种 is-a 关系,也就是通过子类产生的对象一定也是一个父类对象,子类继承了父类的接口。
但是private继承就不是这种关系了,是一种组合关系,是根据…实现出的关系。
这里我们对旧接口私有继承就表示想通过LogToFile类实现出LogAdapter的意思。

这种多重继承的方式来做类适配器,在具体代码的实现中,我们可以直接调用LogToFile接口,不再需要特定的指针。看起来好像很不错,但是实际上是不提倡用类适配器的。

从灵活性上来说,类适配器不如对象适配器,因为private继承方式限制了LogAdapter能调用的LogToFile中的接口。
假如有下面的情况:

class ParClass{....}
class LogToFile:public ParClass{....}

采用对象适配器的话,我只需要在里面定一个ParClass* m_pfile指针,这个指针可以指向任何ParClass的子类对象,有时候这个子类对象可能不止一个。但如果是多重继承,我们需要继承的就不止这一个类了。

总结

一般来说,过多使用适配器模式并不见得是一件好事,因为从表面上看,调用的是A接口,但内部被适配成了调用B接口,这比较容易让人迷惑,一般都是在开发后期不得已才使用这种设计模式。所以,在很多情况下,如果方便对系统进行重构的话,那么以重构来取代适配也许更好。但软件开发中也存在时常要发布新版本的情况,新版本也存在与老版本的兼容性问题,有时完全抛弃老版本并不现实,所以才借助适配器模式使新老版本兼容。在遗留代码的复用、类库的迁移等工作方面,适配器模式仍旧能发挥巨大的作用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2272846.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据挖掘——数据预处理

数据挖掘——数据预处理 数据预处理数据预处理 ——主要任务数据清洗如何处理丢失的数据如何处理噪声数据如何处理不一致数据 数据集成相关分析相关系数(也成为皮尔逊相关系数)协方差 数据规约降维法:PCA主成分分析降数据——抽样法数据压缩 数据预处理 数据预处理…

Unity-Mirror网络框架-从入门到精通之CCU示例

文章目录 前言什么是CCU?测试结果最后 前言 在现代游戏开发中,网络功能日益成为提升游戏体验的关键组成部分。Mirror是一个用于Unity的开源网络框架,专为多人游戏开发设计。它使得开发者能够轻松实现网络连接、数据同步和游戏状态管理。本文…

如何在 Ubuntu 22.04 上安装 Nagios 服务器教程

简介 在本教程中,我们将解释如何在 Ubuntu 22.04 上安装和配置 Nagios,使用 Apache 作为 Web 服务器,并通过 Let’s Encrypt Certbot 使用 SSL 证书进行保护。 Nagios 是一个强大的监控系统,它可以帮助组织在 IT 基础设施问题影…

大语言模型训练所需的最低显存,联邦大语言模型训练的传输优化技术

联邦大语言模型训练的传输优化技术 目录 联邦大语言模型训练的传输优化技术大语言模型训练所需的最低显存大语言模型训练所需的最低显存 基于模型微调、压缩和分布式并行处理的方法,介绍了相关开源模型及技术应用 核心创新点 多维度优化策略:综合运用基于模型微调、模型压缩和…

Javascript算法——贪心算法(一)

贪心算法详解(JavaScript)(局部最优->全局最优) 贪心算法(Greedy Algorithm)是一种在每一步选择中都采取当前状态下的最优选择(局部最优)的算法设计方法。通过局部最优解的累积&…

141.《mac m系列芯片安装mongodb详细教程》

文章目录 下载从官网下载安装包 下载后双击解压出文件夹安装文件名修改为 mongodb配置data存放位置和日志log的存放位置启动方式一方式二方式二:输入mongo报错以及解决办法 本人电脑 m2 pro,属于 arm 架构 下载 官网地址: mongodb官网 怎么查看自己电脑应该下载哪个版本,输入…

【ArcGISPro/GeoScenePro】裁剪和打包栅格数据

检查并处理扫描地图 数据 https://arcgis.com/sharing/rest/content/items/535efce0e3a04c8790ed7cc7ea96d02d/data 使用标准相机或扫描仪创建的数字影像通常存储在 RGB 颜色模型中,这意味着这些影像将由红色、绿色和蓝色三个栅格组成。 此扫描地图在提供给您之前已在坐标系…

【C++】B2109 统计数字字符个数

博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 💯前言💯题目描述与输入输出要求题目:统计数字字符个数样例输入输出 💯方法分析与代码实现方法 1:使用 fgets 读取输入并手动判断数字字符代码实…

基于32单片机的智能语音家居

一、主要功能介绍 以STM32F103C8T6单片机为控制核心,设计一款智能远程家电控制系统,该系统能实现如下功能: 1、可通过语音命令控制照明灯、空调、加热器、窗户及窗帘的开关; 2、可通过手机显示和控制照明灯、空调、窗户及窗帘的开…

git理解记录

文章目录 1. 背景2. 基本概念3. 日常工作流程4. 其他常见操作4.1 merge合并操作4.2 tag打标签操作4.3 remoute远程操作4.4 撤销修改 git理解记录 1. 背景 git作为分布式版本控制系统,开源且免费,相比svn集中式版本控制系统存在速度快(HEAD指针指向某次co…

开启宝塔Nginx防火墙支付返回失败解决方法

1.把/plugin.php加到Nginx防火墙URL白名单 包括支付服务器回调ip 2.如果支持带参数 /plugin.php?idzhifufm:notify 加到Nginx防火墙标准模式-URL白名单带参数 如果上面都不行 就把下面的IP加入白名单 39.107.193.172 47.94.194.103 47.104.216.190

平安产险安徽分公司携手安徽中医药临床研究中心附属医院 共筑儿童安全防护网

为响应金融知识普及教育号召,平安产险安徽分公司联动安徽中医药临床研究中心附属医院,于近日在朝霞小学举办了一场儿童安全防范与健康守护活动。此次活动旨在提升学生的安全防范意识,守护儿童健康成长,同时有力推动金融知识与传统…

Elasticsearch:Lucene 2024 年回顾

作者:来自 Elastic Chris Hegarty 2024 年对于 Apache Lucene 来说又是重要的一年。在本篇博文中,我们将探讨主要亮点。 Apache Lucene 在 2024 年表现出色,发布了许多版本,包括三年来的首次重大更新,其中包含令人兴奋…

Unity打包问题集(持续更新)

1.报错:CommandWithNoStdoutInvokationFailure: Unable to start ADB server. Please make sure the Android SDK is installed and is properly configured in the Editor. See the Console for more details. 大致意思就是打不开ADB的服务器,请检查安卓…

SpringBoot环境和Maven配置

SpringBoot环境和Maven配置 1. 环境准备2. Maven2.1 什么是Maven2.2 为什么要学 Maven2.3 创建一个 Maven项目2.4 Maven核心功能2.4.1 项目构建2.4.2 依赖管理2.4.3 Maven Help插件 2.5 Maven 仓库2.5.1本地仓库2.5.2 中央仓库2.5.3 私有服务器, 也称为私服 2.6 Maven设置国内源…

【HarmonyOS应用开发——ArkTS语言】欢迎界面(启动加载页)的实现【合集】

目录 😋环境配置:华为HarmonyOS开发者 📺演示效果: 📖实验步骤及方法: 一、在media文件夹中添加想要使用的图片素材​ 二、在entry/src/main/ets/page目录下创建Welcome.ets文件 1. 整体结构与组件声…

【数据可视化-11】全国大学数据可视化分析

🧑 博主简介:曾任某智慧城市类企业算法总监,目前在美国市场的物流公司从事高级算法工程师一职,深耕人工智能领域,精通python数据挖掘、可视化、机器学习等,发表过AI相关的专利并多次在AI类比赛中获奖。CSDN…

NLP项目实战——基于Bert模型的多情感评论分类(附数据集和源码)

在当今数字化的时代,分析用户评论中的情感倾向对于了解产品、服务的口碑等方面有着重要意义。而基于强大的预训练语言模型如 Bert 来进行评论情感分析,能够取得较好的效果。 在本次项目中,我们将展示如何利用 Python 语言结合transformers库&…

各种数据库类型介绍

1.关系型数据库(Relational Databases, RDBMS) 关系型数据库是基于关系模型组织的数据库,其数据结构以表格的形式存在,表格之间通过外键等关系相互关联。它们支持复杂的SQL(Structured Query Language)查询…

创龙3588——debian根文件系统制作

文章目录 build.sh debian 执行流程build.sh源码流程 30-rootfs.sh源码流程 mk-rootfs-bullseys.sh源码流程 mk-sysroot.sh源码流程 mk-image.sh源码流程 post-build.sh 大致流程系统制作步骤 build.sh debian 执行流程 build.sh 源码 run_hooks() {DIR"$1"shiftf…