设计模式-11 - Adapter Pattern 适配器设计模式

设计模式-11 - Adapter Pattern 适配器设计模式
 

1.定义


适配器模式是一种结构型设计模式,它允许具有不同接口的两个类一起工作。它通过创建一个适配器类来实现这一点,该适配器类将一个类的接口转换为另一个类所需的接口。

2.内涵


适配器设计模式的内涵在于,它允许具有不同接口的类一起工作,从而提高系统的灵活性、可重用性和松耦合性。

灵活性

适配器模式使系统能够在不修改现有代码的情况下适应新的变化或需求。例如,通过使用适配器,我们可以将旧有的系统与新开发的系统集成,而不需要修改旧有代码。

可重用性

适配器类可以将旧有或不兼容的代码与新系统集成,从而提高代码的可重用性。例如,我们可以创建一个通用适配器,它可以将任何类型的媒体文件转换为所需的格式,而无需为每种文件类型编写特定的转换器。


松耦合

适配器模式通过创建适配器类来实现客户端代码与被适配类的解耦。客户端代码只与适配器交互,而不是直接与被适配类交互。这样,当需要更改被适配类时,客户端代码不受影响。

适配器设计模式背后的基本原理:

  • 接口转换:适配器模式通过创建一个适配器类来转换一个类的接口为另一个类所需的接口。
  • 委托:适配器类通常委托给被适配类来执行实际操作。它充当客户端代码和被适配类之间的桥梁。
  • 多态性:适配器模式利用多态性,允许客户端代码将适配器类视为 Target 接口的实例。
  • 总的来说,适配器设计模式通过在不同接口的类之间提供一个转换层来提高系统的灵活性、可重用性和松耦合性。它使系统能够在不修改现有代码的情况下适应变化,并促进不同组件之间的松散耦合。

3.使用示例
#include <iostream>
#include <string>// Legacy Printer (Adaptee)
class LegacyPrinter {
public:void printInUppercase(const std::string& text){std::cout << "Printing: " << text << std::endl;}
};// Modern Computer (Client)
class ModernComputer {
public:void sendCommand(const std::string& command){std::cout << "Sending command: " << command<< std::endl;}
};// Adapter class to make the LegacyPrinter compatible with
// ModernComputer
class PrinterAdapter {
private:LegacyPrinter legacyPrinter;public:void sendCommand(const std::string& command){// Convert the command to uppercase and pass it to// the LegacyPrinterstd::string uppercaseCommand = command;for (char& c : uppercaseCommand) {c = std::toupper(c);}legacyPrinter.printInUppercase(uppercaseCommand);}
};int main()
{ModernComputer computer;PrinterAdapter adapter;computer.sendCommand("Print this in lowercase");adapter.sendCommand("Print this in lowercase (adapted)");return 0;
}

4.注意事项


在使用适配器设计模式时需要注意以下几点:

  • 性能开销:适配器模式会引入额外的开销,因为适配器类需要在客户端代码和被适配类之间进行转换。对于性能要求很高的场景,这可能是一个考虑因素。
  • 复杂性:适配器模式可以增加系统的复杂性,尤其是在有多个适配器类需要管理时。确保适配器类清晰且易于维护非常重要。
  • 灵活性与松耦合之间的权衡:虽然适配器模式提高了灵活性,但它也可能引入额外的松耦合,这可能会使得追踪和调试问题变得更加困难。在设计适配器时,仔细考虑所需的灵活性级别非常重要。
  • 可重用性:如果适配器类只针对特定的场景或特定类型的适配,则其可重用性可能会受到限制。考虑创建通用适配器,它可以适应更广泛的场景。
  • 测试:确保适配器类经过充分测试,以验证其正确转换接口并委托操作。

此外,在以下情况下,适配器设计模式可能不是最合适的解决方案:

  • 类层次结构不稳定:如果被适配类的接口经常发生变化,则维护适配器类可能会变得困难。
  • 需要双向转换:如果客户端代码和被适配类都需要进行转换,则可以使用桥接模式或外观模式。
  • 可以修改被适配类:如果可以修改被适配类的接口,则可以考虑直接更改其接口以匹配客户端代码所需的接口。


总的来说,在使用适配器设计模式时,权衡其好处和缺点非常重要,并确保它适合特定的场景和需求。


5.最佳实践

(a)适配器设计模式的最佳实践:

  • 遵循接口分离原则(ISP):创建清晰且有明确定义的接口,以便适配器类只实现它所需要的操作。
  • 使用组合而不是继承:适配器类通常使用组合来委托给被适配类,而不是继承自它。这可以避免引入不必要的耦合。
  • 创建通用适配器:如果可能,创建通用适配器,它可以适应多种场景和类型的适配。
  • 保持适配器类轻量级:适配器类应尽可能地保持轻量级,只包含必要的转换逻辑。
  • 充分测试适配器:确保适配器类经过充分测试,以验证其正确转换接口并委托操作。


(b)特别适合适配器设计模式的场景:

  • 整合遗留系统:适配器模式可以将遗留系统与新系统集成,而不需要修改遗留代码。
  • 将第三方库与应用程序集成:适配器模式可以将第三方库的接口转换为应用程序所需的接口。
  • 支持多种格式或协议:适配器模式可以允许系统处理多种格式或协议,而不需要为每种格式或协议编写特定的代码。
  • 解耦不同接口的组件:适配器模式可以解耦具有不同接口的组件,从而提高灵活性并简化维护。
  • 扩展现有类的功能:适配器模式可以扩展现有类的功能,而不需要修改其源代码。


(c)使用示例:

  • 使用适配器将旧的媒体播放器与新系统集成,该系统支持新的媒体格式。
  • 使用适配器将第三方支付网关与电子商务应用程序集成。
  • 使用适配器允许应用程序处理来自不同来源(例如 CSV、XML、JSON)的数据。
  • 使用适配器将图形库与应用程序解耦,以便应用程序可以轻松切换到不同的图形库。
  • 使用适配器扩展现有类的功能,例如添加一个日志记录适配器来记录对象的操作。
6.总结

自定义的适配器,需要考虑确保其既能满足当前需求,又能保持良好的扩展性,为未来需求预留扩展性。

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

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

相关文章

低空经济:无人机竞赛详解

无人机竞赛市场近年来呈现出蓬勃发展的态势&#xff0c;其市场价值不仅体现在竞赛本身&#xff0c;还体现在推动无人机技术创新、拓展应用场景以及促进产业链发展等多个方面。 一、比赛项目介绍 无人机竞赛通常分为多个项目&#xff0c;包括竞速赛、技巧赛、航拍赛等。每个项目…

Ubuntu下C++编程总结AllInOne

之前主要是在win下用VisualStudio&#xff0c;现在研究总结在ubuntu下使用CMake编程经验&#xff0c;填坑记录 目录 0. 前述1.Ubuntu下多线程使用 0. 前述 1.Ubuntu下多线程使用 出现的问题&#xff1a;undefined reference to symbol pthread_create 使用多线程&#xff0c…

HR人才测评:自控能力与岗位胜任力素质测评

自控能力是什么&#xff1f; 自控能力可以解释为自我控制的能力&#xff0c;指一个人在应对人事物突发事件时&#xff0c;及时调整进行的自我控制的表现&#xff0c;它是实行自我支配的一种能力&#xff0c;在能进行自主支配时&#xff0c;一个人就成熟不少了&#xff0c;也可以…

js的跳转传参方式

在JavaScript中&#xff0c;实现页面跳转并传递参数的方式有多种&#xff0c;以下是一些常见的方法&#xff1a; URL参数 你可以通过修改URL的查询字符串&#xff08;query string&#xff09;来传递参数。这些参数会在URL的?之后&#xff0c;并使用&进行分隔。 代码 /…

优选算法——双指针1

双指针 常⻅的双指针有两种形式&#xff0c;⼀种是对撞指针&#xff0c;⼀种是左右指针。 对撞指针&#xff1a;⼀般⽤于顺序结构中&#xff0c;也称左右指针。 对撞指针从两端向中间移动。⼀个指针从最左端开始&#xff0c;另⼀个从最右端开始&#xff0c;然后逐渐往中间逼 近…

std::mem_fn和std::mem_fun

std::mem_fn和std::mem_fun&#xff08;deprecated&#xff09; Convert member function to function object&#xff0c;即将成员函数转化为函数对象&#xff0c;这样就可以像普通函数那样使用。 示例一&#xff1a; #include <iostream> // std::cout #include …

MySQL-InnoDB数据存储结构

1、存储结构-页 索引结构提供了高效的索引方式&#xff0c;索引信息以及数据记录都保存在数据文件或索引文件中&#xff08;本质存储在页结构中&#xff09; 1.1、磁盘与内存交互的基本单位&#xff1a;页 在InnoDB中将数据划分为若干页&#xff0c;页的默认大小为&#xff…

webpack并行构建示例:

由于js的单线程特性&#xff0c;文件和任务时 要等待一个任务执行完成后执行下一个任务&#xff0c;但在实际开发中&#xff0c;很多任务是可以并行执行的&#xff08;如同时处理多个不同js文件或同事压缩多张图片&#xff09;&#xff0c;一些loader和插件&#xff08;thread-…

【数据结构】解密链表之旅(单链表篇)

前言 哈喽大家好&#xff0c;我是野生的编程萌新&#xff0c;首先感谢大家的观看。数据结构的学习者大多有这样的想法&#xff1a;数据结构很重要&#xff0c;一定要学好&#xff0c;但数据结构比较抽象&#xff0c;有些算法理解起来很困难&#xff0c;学的很累。我想让大家知道…

自制无感无刷电机驱动板

自制无感无刷电机驱动板 分别测试了基于C251的STC32G单片机、Arduino AVR的ATmega328PB、以及ARM的ST32F103单片机。 &#x1f9f2;测试转动效果 ✒目前市面上开源的有关无刷电机的项目数不胜数&#xff0c;其控制原理都大同小异&#xff0c;在没有领透其技术要领情况下&#x…

苍穹外卖项目---------收获以及改进(9-12)

①Spring Task-------实现系统定时任务 概念&#xff1a; 应用场景&#xff1a; 使用步骤&#xff1a; 实现订单超时和前一天派送中的订单的自动任务处理&#xff1a; Component Slf4j public class Mytask {Autowiredprivate OrderServiceimpl orderServiceimpl;/*** 处理订…

yarn 安装以及报错处理

前一种报错是由于没有安装yarn导致的&#xff0c;使用以下命令即可安装&#xff1a; npm install -g yarn 如果成功安装&#xff0c;将显示Yarn的版本号。 yarn --version 第二种报错是因为系统上的执行策略限制导致的。执行策略是一种安全功能&#xff0c;用于控制在计算机…

grafana10.x报错 Failed to upgrade legacy queries Datasource x was not found

问题 grafana 从6.x升级到10.x后&#xff0c;导入json文件后报错&#xff0c;数据源x查询不到&#xff0c;grafana不显示数据&#xff1b; Templating Failed to upgrade legacy queries Datasource x was not found解决方法 可能grafana升级后数据源找不到&#xff0c;在面板…

上海市计算机学会竞赛平台2023年10月月赛丙组三个数的中位数

题目描述 给定三个整数&#xff0c;请输出按大小排序后&#xff0c;位于正中间的数字。 输入格式 第一行&#xff1a;三个整数 &#x1d44e;a, &#x1d44f;b 与 &#x1d450;c 输出格式 第一行&#xff1a;单个整数表示三者的中位数 数据范围 −10000≤&#x1d44e…

CentOS7 源码编译 rtpengine9.5.8

CentOS7 不好搞&#xff0c;但应客户要求&#xff0c;不得不搞 选择 rtpengine9.5.8 版本而不是更新的版本&#xff0c;肯定是有自己的考虑的 不废话了&#xff0c;直接上脚本&#xff1a; #!/bin/bash# CentOS7 最小安装yum -y install epel-release yum -y install git gc…

Kafka官方文档中文版+Kafka面试题详解!

你了解kafka吗&#xff1f;目前它在一线互联网公司以迅雷不及掩耳之势得到了广泛的应用。但究竟是什么呢&#xff1f;Kafka最初于2011年在LinkedIn开发&#xff0c;自那时起经历了很多改进。如今它是一个完整的平台&#xff0c;允许您冗余地存储荒谬的数据量&#xff0c;拥有一…

SH150S1光电吊舱

SH150S1光电吊舱 1产品应用 SH150S1是一款三轴三光吊舱&#xff0c;集成了最远测程达3.0km&#xff0c;精度小于2米的半导体激光测距机&#xff0c;640512高分辨率红外相机&#xff0c;30倍光学变倍可见光相机以及高稳定精度平台框架&#xff1b;可安装于中小型无人机&#x…

【每日刷题】Day40

【每日刷题】Day40 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. 202. 快乐数 - 力扣&#xff08;LeetCode&#xff09; 2. 217. 存在重复元素 - 力扣&#xff08;Le…

vue2 报错,警告 解决方法 component name“Index“should always be multi-word

报错原因&#xff1a; 组件名称应该为俩个或俩个以上单词组成的&#xff0c;并且还要是大驼峰命名&#xff0c;例如&#xff1a;MyIndex&#xff0c;MyLogin等 解决方法一&#xff1a; 将组件名称改为俩个或俩个以上单词组成的名称&#xff0c;且为大驼峰命名&#xff0c;例如…

前端手写练习题及概念加深

通过举例和实际例子来加深前端的概念形式 1. 手写reduce 用法&#xff1a; // 手写 reduce const a [1, 3, 6, 8]const sum a.reduce((accu, curr) > accu curr, 0) console.log(sum, sum ) 在注释中解释 reduce 的手写方法 // 1. 明确参数累加函数&#xff0c;接受…