Python 如何实现适配器设计模式?什么是适配器(Adapter)设计模式?

什么是适配器设计模式?

适配器(Adapter)设计模式是一种结构型设计模式,它允许接口不兼容的类之间进行合作。适配器模式充当两个不兼容接口之间的桥梁,使得它们可以一起工作,而无需修改它们的源代码。

在这里插入图片描述

主要角色:

  1. 目标接口(Target): 定义客户端使用的接口,客户端通过该接口与适配器进行交互。

  2. 适配器(Adapter): 实现目标接口,并且持有一个被适配者的实例,将客户端的请求转换为被适配者能够处理的形式。

  3. 被适配者(Adaptee): 拥有一组不兼容目标接口的方法,适配器通过包装被适配者,使其能够与目标接口协同工作。

  4. 客户端(Client): 通过目标接口与适配器进行交互,无需直接与被适配者打交道。

工作流程:

  1. 客户端通过目标接口调用适配器的方法。

  2. 适配器内部持有一个被适配者的实例。

  3. 适配器将客户端的请求转换为被适配者能够理解的形式。

  4. 被适配者处理请求并返回结果。

  5. 适配器将结果转换为客户端期望的形式并返回。


Python 适配器设计模式示例代码(一):

假设有一个英语到法语的翻译器,但客户端只能接受英语接口,这时就需要适配器来转换法语接口为英语接口。

from abc import ABC, abstractmethod

# 目标接口
class EnglishSpeaker(ABC):
    @abstractmethod
    def speak_english(self):
        pass

# 被适配者
class FrenchSpeaker:
    def parler_francais(self):
        return "Je parle français"

# 适配器
class FrenchToEnglishAdapter(EnglishSpeaker):
    def __init__(self, french_speaker):
        self.french_speaker = french_speaker

    def speak_english(self):
        french_phrase = self.french_speaker.parler_francais()
        # 这里可以进行一些转换操作,这里简单地将法语短语翻译成英语
        english_translation = "I speak English: " + french_phrase
        return english_translation

# 客户端
def communicate_in_english(english_speaker):
    print(english_speaker.speak_english())

# 创建被适配者
french_speaker = FrenchSpeaker()

# 创建适配器
adapter = FrenchToEnglishAdapter(french_speaker)

# 客户端调用
communicate_in_english(adapter)

在这个示例中,EnglishSpeaker 是目标接口,FrenchSpeaker 是被适配者,FrenchToEnglishAdapter 是适配器。客户端通过目标接口与适配器交互,而适配器内部调用了被适配者的方法,将其转换为目标接口的形式。这使得客户端能够通过目标接口与被适配者进行通信。


Python3 适配器设计模式示例代码(二)

假设有一个系统,其中已经存在一个用于存储数据的类 Database,该类有一个名为 store_data 的方法。现在我们引入一个新的需求,需要将数据存储到云服务中,但云服务的接口与 Database 类的接口不同。我们可以使用适配器模式来使新的云服务类与现有的系统协同工作。

# 现有的数据库类
class Database:
    def store_data(self, data):
        print(f"Storing data in the local database: {data}")

# 云服务类(被适配者)
class CloudService:
    def upload(self, data):
        print(f"Uploading data to the cloud: {data}")

# 适配器
class CloudServiceAdapter(Database):
    def __init__(self, cloud_service):
        self.cloud_service = cloud_service

    def store_data(self, data):
        # 转换并调用云服务的接口
        cloud_data = self.convert_to_cloud_format(data)
        self.cloud_service.upload(cloud_data)

    def convert_to_cloud_format(self, data):
        # 在适配器中进行数据格式的转换
        return f"[Converted] {data}"

# 客户端代码
def save_data(database, data):
    database.store_data(data)

# 创建现有的数据库对象
local_database = Database()

# 客户端使用现有的数据库
save_data(local_database, "Some data")

# 创建云服务对象
cloud_service = CloudService()

# 创建适配器对象,使云服务与数据库接口兼容
cloud_service_adapter = CloudServiceAdapter(cloud_service)

# 客户端使用适配器,实际上调用了云服务的接口
save_data(cloud_service_adapter, "Data for the cloud")

在这个示例中,CloudService 类是被适配者,其接口与 Database 类不同。通过创建 CloudServiceAdapter 类,我们使得 CloudService 类能够适配到原有的系统中,客户端代码可以通过调用 store_data 方法来统一处理数据存储,而无需关心具体是本地数据库还是云服务。这种适配器模式的应用场景在实际开发中很常见,特别是在集成新的服务或组件时。


在实现适配器设计模式时,有哪些需要注意的地方?

在实现适配器设计模式时,有一些需要注意的地方,以确保模式的有效实施和系统的可维护性:

  1. 接口一致性: 确保适配器实现了目标接口,以便客户端可以一致地使用适配器和原始对象。

  2. 被适配者的接口: 确保理解被适配者的接口,了解如何将其转换为目标接口。这可能涉及到数据格式的转换、方法名称的改变等。

  3. 单一职责原则: 适配器通常需要处理两个不同接口之间的转换,但避免将太多的功能放入适配器,以确保每个类都遵循单一职责原则。

  4. 适配器类型: 适配器可以采用对象适配器或类适配器的形式。对象适配器使用组合,类适配器使用继承。选择适合你需求的适配器类型。

  5. 被适配者对象引入方式: 被适配者对象可以通过构造函数、初始化方法或其他方式引入。确保适配器能够持有被适配者对象的引用。

  6. 数据转换: 如果需要在适配器中进行数据格式的转换,确保转换是正确的,并且不会丢失关键信息。

  7. 异常处理: 考虑被适配者可能抛出的异常,确保适配器能够适当地处理这些异常或将其转换为适当的形式。

  8. 命名清晰: 适配器类的命名应当清晰地反映其用途,以便其他开发人员能够轻松理解和使用。

  9. 兼容性: 考虑被适配者和目标接口的未来变化,以确保适配器仍然能够正确工作。

  10. 测试: 编写充分的测试来验证适配器的正确性。测试应该覆盖适配器的所有行为,包括对不同接口的适应性。

  11. 文档: 提供清晰的文档,说明适配器的使用方式、目的和注意事项。这有助于其他开发人员更容易理解和使用适配器。

通过关注这些方面,可以确保适配器设计模式在系统中的有效应用。适配器模式通常用于集成新的组件、服务或库时,能够使不同接口的类能够协同工作。


本文就到这里了,感谢您的阅读 。别忘了点赞、收藏~ Thanks♪(・ω・)ノ 🍇

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CTFhub-RCE-过滤空格

1. 查看当前目录&#xff1a;127.0.0.1|ls 2. 查看 flag_890277429145.php 127.0.0.1|cat flag_890277429145.php 根据题目可以知道空格被过滤掉了 3.空格可以用以下字符代替&#xff1a; < 、>、<>、%20(space)、%09(tab)、$IFS$9、 ${IFS}、$IFS等 $IFS在li…

03.智慧商城——封装请求模块、登录静态页面、图形验证码

01. 登录页静态布局 (1) 准备工作 新建 styles/common.less 重置默认样式 // 重置默认样式 * {margin: 0;padding: 0;box-sizing: border-box; }// 文字溢出省略号 .text-ellipsis-2 {overflow: hidden;-webkit-line-clamp: 2;text-overflow: ellipsis;display: -webkit-box…

C++标准模板(STL)- 类型支持 (属性查询,获取类型的对齐要求)

类型特性 类型特性定义一个编译时基于模板的结构&#xff0c;以查询或修改类型的属性。 试图特化定义于 <type_traits> 头文件的模板导致未定义行为&#xff0c;除了 std::common_type 可依照其所描述特化。 定义于<type_traits>头文件的模板可以用不完整类型实例…

本地视频AI人脸替换,一键启动,傻瓜式操作

本地无须准备配置和运行环镜&#xff0c;整个压缩包下载后解压&#xff0c;一键启动程序&#xff0c;只需一张照片和一个视频&#xff0c;就可以把视频中的人物替换成您想要的人脸。支持CPU和GPU解码&#xff0c;使用GPU解码速度较快。 所有使用的软件安装包已上传网盘&#x…

Ubuntu 20.04 调整交换分区大小

Ubuntu 调整交换分区大小 一、系统情况二、去除旧的交换分区文件三、配置并启用交换分区四、查看swap文件大小 一、系统情况 Ubuntu &#xff1a;Ubuntu 20.04.6 LTS 交换分区位置&#xff1a; cat /proc/swaps二、去除旧的交换分区文件 去掉旧的交换分区有两个步骤&#x…

【excel技巧】Excel表格里的图片如何批量调整大小?

Excel表格里面插入了很多图片&#xff0c;但是每张图片大小不一&#xff0c;如何做到每张图片都完美的与单元格大小相同&#xff1f;并且能够根据单元格来改变大小&#xff1f;今天分享&#xff0c;excel表格里的图片如何批量调整大小。 方法如下&#xff1a; 点击表格中的一…

DBA_IND_STATISTICS 字段含义

功能 展示数据库中所有索引的优化器统计信息。 字段说明 参考&#xff1a;https://www.oceanbase.com/docs/enterprise-oceanbase-database-cn-10000000000885743

贝加莱软件功能测试

通讯及稳定性测试 Profibus DP通讯、Modbus通讯、CANOPEN通讯测试 C1 C2 C3 测试目的 测试验证贝加莱控制系统各种现场总线通讯的性能及稳定性。验收标准 主站PLC可与现有总线仪表建立Profibus DP通讯、Modbus通讯或CANOPEN通讯&#xff0c;连续运行&#xff08;通讯状态应保…

万能自定义表单系统源码 支持收费表单+在线支付+活动报名 带前后端完整部署教程

随着互联网的快速发展&#xff0c;各种在线表单系统已经成为了许多企业和个人的必备工具。这些表单系统可以帮助用户收集信息、管理数据、进行在线支付等操作。然而&#xff0c;现有的表单系统往往不能满足所有用户的需求&#xff0c;所以这款万能自定义表单系统源码应用而生。…

内衣洗衣机和手洗哪个干净?迷你洗衣机品牌推荐

很多人会觉得内衣洗衣机是智商税&#xff0c;洗个内衣只需要两分钟的事情&#xff0c;需要花个几百块钱去入手一个洗衣机吗&#xff1f;然而清洗贴身衣物的并不是一件简单的事情&#xff0c;如果只是简单的搓洗&#xff0c;内裤上看不见的细菌也无法消除&#xff0c;而且对来生…

【ROS导航Navigation】五 | 导航相关的消息 | 地图 | 里程计 | 坐标变换 | 定位 | 目标点和路径规划 | 激光雷达 | 相机

致谢&#xff1a;ROS赵虚左老师 Introduction Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程 参考赵虚左老师的实战教程 一、地图 nav_msgs/MapMetaData 地图元数据&#xff0c;包括地图的宽度、高度、分辨率等。 nav_msgs/OccupancyGrid 地图栅格数据&#…

Outlook搜索功能灰色

Outlook搜索功能灰色 故障现象&#xff1a; Outlook搜索邮件功能突然灰色&#xff0c;无法搜索邮件&#xff0c;搜索栏直接搜索的结果不准确&#xff0c;并提示服务被禁用。 故障截图&#xff1a; 故障原因&#xff1a; Windows search服务被禁用导致&#xff0c;需要重新开…

人工智能为游戏带来提升

人工智能为游戏带来提升 1提升游戏体验 提高吸引力 ​ 游戏中的****NPC 首先&#xff0c;出现和玩家相同水平&#xff08;甚至超越人类的&#xff09;的电脑玩家就已经足够吸引人了&#xff0c;尤其是一些游戏中如果可以产生一个和人类更加相似的NPC&#xff0c;无疑可以让玩…

论文阅读——RetNet

transformer的问题&#xff1a;计算量大&#xff0c;占用内存大&#xff0c;不好部署。 所以大家在找能解决办法&#xff0c;既能和transformer表现一样好&#xff0c;又能在推理阶段计算复杂度很低。 这些方法大概分类三类&#xff1a;一是代替transformer非线性注意力机制的…

MVMD(多元变分模态分解)

代码使用方法 多元变分模态分解 代码原理 多元变分模态分解(Multivariate Variational Mode Decomposition, MVMD)是一种信号分解方法&#xff0c;用于从多元时间序列数据中提取模态成分。 传统的变分模态分解(Variational Mode Decomposition, VMD)是一种基于优化方法的信号…

【税收相关】企业所得税值税、消费税、企业所得税、个人所得税、资源税、城市维护建设税、房产税、印花税、城镇土地使用税、土地增值税

【点我-这里送书】 本人详解 作者&#xff1a;王文峰&#xff0c;参加过 CSDN 2020年度博客之星&#xff0c;《Java王大师王天师》 公众号&#xff1a;JAVA开发王大师&#xff0c;专注于天道酬勤的 Java 开发问题中国国学、传统文化和代码爱好者的程序人生&#xff0c;期待你的…

3.1 Windows驱动开发:内核远程堆分配与销毁

在开始学习内核内存读写篇之前&#xff0c;我们先来实现一个简单的内存分配销毁堆的功能&#xff0c;在内核空间内用户依然可以动态的申请与销毁一段可控的堆空间&#xff0c;一般而言内核中提供了ZwAllocateVirtualMemory这个函数用于专门分配虚拟空间&#xff0c;而与之相对应…

Mac电脑好用的窗口管理软件 Magnet 中文for mac

Magnet是一款用于Mac操作系统的窗口管理工具&#xff0c;它可以帮助您快速和方便地组织和管理应用程序窗口&#xff0c;以提高您的工作效率和多任务处理能力。 以下是Magnet的一些主要功能和特点&#xff1a; 窗口自动调整&#xff1a;Magnet允许您通过简单的拖放操作或使用快…

计算机毕业设计选题推荐-一周穿搭推荐微信小程序/安卓APP-项目实战

✨作者主页&#xff1a;IT研究室✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

python之使用深度学习创建自己的表情符号

目录 部署项目1、首先运行train.py训练模型2、接下运行gui.py测试 一、使用 CNN 进行面部情绪识别二、GUI 代码和表情符号映射 在这个深度学习项目中&#xff0c;我们将对人类面部表情进行分类&#xff0c;以过滤和映射相应的表情符号或头像。 数据集&#xff08;面部表情识别&…