重温设计模式--适配器模式

文章目录

  • 适配器模式(Adapter Pattern)概述
  • 适配器模式UML图
  • 适配器模式的结构
    • 目标接口(Target):
    • 适配器(Adapter):
    • 被适配者(Adaptee):
  • 作用:
  • C++ 代码示例
  • C++示例代码2
  • 应用场景
    • 系统集成与接口兼容
    • 第三方库集成:
    • 旧代码适配新架构:
    • 软件模块交互与协作
    • 跨平台开发中的适配:

适配器模式(Adapter Pattern)概述

定义:
适配器模式是一种结构型设计模式,它的主要作用是将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的类可以协同工作。就好像一个 “转换器”,把不匹配的接口进行适配,让它们能够相互对接使用。

适配器模式UML图

在这里插入图片描述

适配器模式的结构

目标接口(Target):

这是客户端所期望使用的接口,定义了客户端需要调用的方法集合。它代表了一种规范或者协议,客户端代码是基于这个接口来进行操作的。

适配器(Adapter):

它实现了目标接口,同时在内部持有一个被适配者的实例,并通过调用被适配者的相关方法来实现目标接口中定义的方法,以此来完成接口的转换工作,使得客户端可以通过目标接口来间接使用被适配者的功能。

被适配者(Adaptee):

它是已经存在的、具有特定功能但接口不符合要求的类或对象。其接口可能包含与目标接口相似但不完全相同的方法,或者方法名称、参数等方面存在差异。

作用:

解决接口不兼容问题:在软件开发过程中,经常会遇到需要使用一些现有的类,但这些类的接口与当前系统所期望的接口不一致的情况。适配器模式通过创建一个中间适配器类,对原有类的接口进行包装转换,使其符合新的使用要求,从而避免了对原有类进行大规模修改,保护了已有的代码资产。
提高代码的复用性:可以复用那些已经经过测试、功能完善但接口不符合要求的类,只需要添加适配器类来适配接口,就能让它们融入新的系统环境中继续发挥作用,减少了重复开发的工作量。
增强系统的灵活性和可扩展性:当系统需要接入新的外部组件或者更换底层实现时,如果存在接口不兼容的情况,通过编写适配器就能方便地实现对接,使得系统可以更容易地与不同的外部模块集成,应对各种变化。

C++ 代码示例

以下以一个简单的电源适配器的例子来展示适配器模式在代码中的应用。假设我们有一个手机充电器,它期望的输入电压是 5V,而我们现有的电源输出电压是 220V,需要一个适配器来将 220V 的电压转换为 5V 供手机充电器使用。

// 目标接口,代表手机充电器期望的输入接口
class ChargerTarget{
public:virtual void chargeWith5V() = 0;
};// 被适配者,代表现有的220V电源,有输出220V电压的方法
class PowerSource 
{
public:void output220V() {std::cout << "输出220V电压" << std::endl;}
};// 适配器类,将220V电源适配成手机充电器能用的5V电源
class VoltageAdapter : public ChargerTarget{
private:PowerSource* powerSource;
public:VoltageAdapter(PowerSource* source){powerSource = source;}void chargeWith5V() override{powerSource->output220V();std::cout << "经过适配器转换,输出5V电压用于充电" << std::endl;}
};int main() 
{PowerSource powerSource;VoltageAdapter adapter(&powerSource);ChargerTarget* charger = &adapter;charger->chargeWith5V();return 0;
}

在上述代码中:
ChargerTarget是目标接口,定义了chargeWith5V方法,代表手机充电器期望的输入接口规范,客户端希望调用这个接口来实现充电功能。
PowerSource是被适配者,它原本有自己的output220V方法,输出的是 220V 电压,不符合手机充电器直接使用的要求。
VoltageAdapter是适配器类,它实现了ChargerTarget接口,内部持有PowerSource对象的指针。在chargeWith5V方法中,先调用PowerSource的output220V方法获取 220V 电压,然后模拟进行转换,输出符合要求的 5V 电压,从而使得原本不匹配的电源和手机充电器能够协同工作,体现了适配器模式的基本原理和应用方式。
除了这种类适配器的形式(通过继承来实现适配),还有对象适配器(通过组合的方式,将被适配者对象作为适配器类的成员变量,代码结构稍有不同,但核心思想一致),可根据具体的应用场景和设计需求来选择合适的实现方式。

C++示例代码2

#include<iostream>
#include<string>
using namespace std;
//抽象球员类
class player
{protected:string m_name;
public:player(string str_name):m_name(str_name){}virtual void attack(){};virtual void defends(){};
};
//具体球员 前锋
class forwords:public player
{
public:forwords(string str_name):player(str_name){}void attack(){cout<<m_name<<"进攻"<<endl;}void defends(){cout<<m_name<<"防守"<<endl;}
};
//中锋
class center:public player
{
public:center(string str_name):player(str_name){}void attack(){cout<<m_name<<"进攻"<<endl;}void defends(){cout<<m_name<<"防守"<<endl;}
};class yaoming
{
private:string m_name;
public:yaoming(string str_name):m_name(str_name){}void attack_yaoming(){cout<<m_name<<"进攻"<<endl;}void defends_yaoming(){cout<<m_name<<"防守"<<endl;}
};class translate:public player
{
private:yaoming *s;
public:translate(string str_name):player(str_name){s = new yaoming("姚明");}void attack(){s->attack_yaoming();}void defends(){s->defends_yaoming();}};int main()
{player *s = new forwords("A");s->attack();player *s1 = new forwords("B");s1->attack();player *m_yaoming = new translate("姚明");m_yaoming->defends();m_yaoming->attack();return 0;
}

应用场景

系统集成与接口兼容

不同数据库的适配:当应用程序需要从一个数据库系统(如 MySQL)切换到另一个数据库系统(如 Oracle)时,由于数据库的 API 接口不同,就可以使用适配器模式。例如,原来的代码是基于 MySQL 的SELECT语句来查询数据,接口可能是mysql_query()函数。当切换到 Oracle 时,其查询接口是OCIStmtExecute()函数。可以创建一个适配器类,实现原来基于 MySQL 接口风格的函数,在内部将其转换为 Oracle 对应的函数调用,这样就可以在不大量修改上层业务逻辑代码的情况下完成数据库的替换。

第三方库集成:

在软件开发中,常常会使用第三方库来实现一些功能。如果第三方库的接口与项目中其他部分的接口不兼容,就可以使用适配器模式来整合。比如,一个图形绘制库的接口是接收坐标点的数组来绘制多边形,而项目中现有的图形数据存储格式是一系列的线段对象。这时可以创建一个适配器,将线段对象转换为坐标点数组的格式,使其能够被图形绘制库所使用。
旧系统改造与复用

旧代码适配新架构:

在对旧系统进行升级改造时,可能会引入新的架构或者设计模式。如果旧系统中的一些功能模块的接口不符合新架构的要求,就可以通过适配器模式来进行适配。例如,旧系统中有一个用户认证模块,它的接口是直接返回用户的基本信息字符串,而新架构要求通过一个对象来传递用户信息,包括用户名、密码、权限等多个属性。可以创建一个适配器类,将旧接口返回的字符串解析并封装成新架构所需要的用户信息对象,从而使旧的用户认证模块能够在新架构中继续使用。
硬件设备接口适配:在工业控制或者智能家居系统中,可能会存在新的控制系统与旧的硬件设备接口不匹配的情况。例如,新的智能控制系统期望通过网络协议接收和发送设备状态信息,而旧的传感器设备只有简单的串口通信接口并且数据格式不同。通过适配器模式,可以创建一个设备接口适配器,将串口通信的数据格式转换为网络协议的数据格式,并且处理通信方式的差异,使得旧设备能够在新的智能控制系统中正常工作。

软件模块交互与协作

不同模块间接口转换:在一个大型软件系统中,不同的模块可能是由不同的团队开发的,它们的接口设计可能没有考虑到相互之间的协作。当需要将这些模块集成在一起时,就可能会出现接口不兼容的问题。例如,一个数据处理模块输出的数据结构是链表形式,而另一个数据分析模块期望的数据结构是数组形式。可以通过适配器模式,创建一个数据结构适配器,将链表数据转换为数组数据,使得两个模块能够顺利地进行数据交互。

跨平台开发中的适配:

在跨平台应用开发中,不同的操作系统(如 Windows、Linux、macOS)提供的 API 接口有所不同。例如,在 Windows 系统中,创建窗口的函数是CreateWindow(),而在 Linux 系统下可能是通过XCreateWindow()函数(基于 X Window 系统)。为了使应用程序能够在不同的操作系统上运行,可以使用适配器模式。创建一个窗口创建适配器类,在不同的操作系统下实现不同的窗口创建函数,但是对外提供统一的窗口创建接口,这样就可以在跨平台开发中方便地处理操作系统接口的差异。

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

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

相关文章

C语言项目 天天酷跑(上篇)

前言 这里讲述这个天天酷跑是怎么实现的&#xff0c;我会在天天酷跑的下篇添加源代码&#xff0c;这里会讲述天天酷跑这个项目是如何实现的每一个思路&#xff0c;都是作者自己学习于别人的代码而创作的项目和思路&#xff0c;这个代码和网上有些许不一样&#xff0c;因为掺杂了…

公交车信息管理系统:构建智能城市交通的基石

程序设计 本系统主要使用Java语言编码设计功能&#xff0c;MySQL数据库管控数据信息&#xff0c;SSM框架创建系统架构&#xff0c;通过这些关键技术对系统进行详细设计&#xff0c;设计和实现系统相关的功能模块。最后对系统进行测试&#xff0c;这一环节的结果&#xff0c;基本…

MDS-NPV/NPIV

在存储区域网络&#xff08;SAN&#xff09;中&#xff0c;域ID&#xff08;Domain ID&#xff09;是一个用于区分不同存储区域的关键参数。域ID允许SAN环境中的不同部分独立操作&#xff0c;从而提高效率和安全性。以下是关于域ID的一些关键信息&#xff1a; 域ID的作用&…

【网络安全产品大调研系列】1. 漏洞扫描

1. 为什么会出现漏扫技术&#xff1f; 每次黑客攻击事件进行追溯的时候&#xff0c;根据日志分析后&#xff0c;我们往往发现基本都是系统、Web、 弱口令、配置这四个方面中的其中一个出现的安全问题导致黑客可以轻松入侵的。 操作系统的版本滞后&#xff0c;没有更新补丁&am…

验证 Dijkstra 算法程序输出的奥秘

一、引言 Dijkstra 算法作为解决图中单源最短路径问题的经典算法,在网络路由、交通规划、资源分配等众多领域有着广泛应用。其通过不断选择距离源节点最近的未访问节点,逐步更新邻居节点的最短路径信息,以求得从源节点到其他所有节点的最短路径。在实际应用中,确保 Dijkst…

【论文阅读笔记】Learning to sample

Learning to sample 前沿引言方法问题声明S-NET匹配ProgressiveNet: sampling as ordering 实验分类检索重建 结论附录 前沿 这是一篇比较经典的基于深度学习的点云下采样方法 核心创新点&#xff1a; 首次提出了一种学习驱动的、任务特定的点云采样方法引入了两种采样网络&…

Mysql大数据量表分页查询性能优化

一、模拟场景 1、产品表t_product,数据量500万+ 2、未做任何优化前,cout查询时间大约4秒;LIMIT offset, count 时,offset 值较大时查询时间越久。 count查询 SELECT COUNT(*) AS total FROM t_product WHERE deleted = 0 AND tenant_id = 1 分页查询 SELECT * FROM t_…

pythonWeb~伍~初识Django

初识Django 1.技术栈 Python知识点&#xff1a;函数、面向对象。前端知识点&#xff1a;HTML、CSS、JavaScript、jQuery、BootStrap。MySQL数据库。Python的Web框架&#xff1a; Flask&#xff0c;自身短小精悍 第三方组件。Django&#xff0c;内部已集成了很多组件 第三方…

kimi搜索AI多线程批量生成txt原创文章软件-不需要账号及key

kimi搜索AI多线程批量生成txt原创文章软件介绍&#xff1a; 软件可以设置三种模型写文章&#xff1a;kimi&#xff1a;默认AI模型&#xff0c;kimi-search&#xff1a;联网检索模型 &#xff0c;kimi-research&#xff1a;探索版搜索聚合模型 1、可以设置写联网搜索文章&#…

DevNow x Notion

前言 Notion 应该是目前用户量比较大的一个在线笔记软件&#xff0c;它的文档系统也非常完善&#xff0c;支持多种文档格式&#xff0c;如 Markdown、富文本、表格、公式等。 早期我也用过一段时间&#xff0c;后来有点不习惯&#xff0c;就换到了 Obsidian &#xff0c;但是…

CSPM认证最推荐学习哪个级别?

一、什么是CSPM&#xff1f; CSPM的全称是Certified Strategic Project Manager&#xff0c;中文名称为“项目管理专业人员能力评价等级证书”。这是由中国标准化协会依据国家标准《项目管理专业人员能力评价要求》&#xff08;GB/T 41831-2022&#xff09;推出的一项认证&…

oracle: create new database

用database configuration Assistant 引导创建数据库。记得给system,sys 设置自己的口令&#xff0c;便于添加新操作用户。 创建操作用户&#xff1a; -- 别加双引号&#xff0c;否则&#xff0c;无法用 create user geovindu identified by 888888; create user geovin identi…

快速建站(网站如何在自己的电脑里跑起来) 详细步骤 一

1.选择开源网站 开源网站的建设平台有多种类型&#xff0c;每种类型都针对不同的需求和用途。我们根据自己的需求来选择 一、内容管理系统&#xff08;CMS&#xff09; 内容管理系统是开源网站建设中最常见的类型之一&#xff0c;它们提供了一个易于使用的界面&#xff0c;使用…

ECharts散点图-气泡图,附视频讲解与代码下载

引言&#xff1a; ECharts散点图是一种常见的数据可视化图表类型&#xff0c;它通过在二维坐标系或其它坐标系中绘制散乱的点来展示数据之间的关系。本文将详细介绍如何使用ECharts库实现一个散点图&#xff0c;包括图表效果预览、视频讲解及代码下载&#xff0c;让你轻松掌握…

【蓝桥杯——物联网设计与开发】拓展模块5 - 光敏/热释电模块

目录 一、光敏/热释电模块 &#xff08;1&#xff09;资源介绍 &#x1f505;原理图 &#x1f505;AS312 &#x1f319;简介 &#x1f319;特性 &#x1f505;LDR &#xff08;2&#xff09;STM32CubeMX 软件配置 &#xff08;3&#xff09;代码编写 &#xff08;4&#x…

Escalate_Linux靶机

Escalate_Linux靶机 前言&#xff1a;集合了多种liunx提权方法的靶场&#xff0c;通过该靶场可以简单的了解liunx提权方法 1&#xff0c;扫描一下端口 80/tcp open http 111/tcp open rpc 2049/udp nfs要知道对方的共享才能挂载 139/445 Samba SMB是一个协议名&#xff0c…

PPO算法基础(一)

PPO近端策略优化算法 我们今天还是主要来理解PPO算法的数学原理。PPO是一种策略梯度方法&#xff0c;简单的策略梯度对每个样本&#xff08;或者一组样本&#xff09;进行一次梯度更新&#xff0c;对单个样本执行多个梯度步骤会导致一些问题&#xff0c;因为梯度偏差太大&…

[机器学习]sklearn入门指南(1)

简介 scikit-learn&#xff08;简称sklearn&#xff09;是一个开源的Python机器学习库&#xff0c;它提供了简单而高效的工具用于数据挖掘和数据分析&#xff0c;并且拥有一个活跃的开发社区。它建立在NumPy、SciPy和matplotlib这些科学计算库之上&#xff0c;旨在提供一致且可…

贪心算法(三)

目录 一、k次取反后最大化的数组和 二、优势洗牌 三、最长回文串 四、增减字符串匹配 一、k次取反后最大化的数组和 k次取反后最大化的数组和 贪心策略&#xff1a; 解题代码&#xff1a; class Solution { public:int largestSumAfterKNegations(vector<int>&am…

文本的AIGC率检测原理

背景 你可能在学生群里或者视频中看过这样的消息&#xff1a;“我们学校要求论文AI率不能超过30%&#xff01;”、“你们学校查AI率吗&#xff1f;”之类的&#xff0c;这些消息到底是真是假&#xff1f; 随着人工智能的快速发展和广泛应用&#xff0c;不论是工作中还是学生学…