【设计模式】深入理解Python中的适配器模式(Adapter Pattern)
深入理解Python中的适配器模式(Adapter Pattern)
在软件开发中,常常会遇到需要让不兼容的类或接口协同工作的问题。适配器模式(Adapter Pattern)是一种结构型设计模式,通过提供一个包装器对象,将一个类的接口转换成客户端期望的另一种接口,从而解决类接口不兼容的问题。
本文将详细探讨适配器模式的定义、应用场景、实现步骤,以及如何在Python中实现该模式,并探讨其优缺点及扩展。
1. 什么是适配器模式?
适配器模式是一种结构型设计模式,它允许我们将一个类的接口转换成另一类的接口,使得原本由于接口不兼容而无法一起工作的类可以协同工作。适配器模式的核心思想是创建一个包装类,该类包装了现有的类,并通过包装的方式为客户端提供期望的接口。
适配器模式的角色
适配器模式主要包括以下几个角色:
- 目标接口(Target):客户端期望使用的接口或抽象类。
- 现有类(Adaptee):需要适配的现有类,它具有不兼容的接口。
- 适配器(Adapter):适配器类负责将
Adaptee
的接口转换成Target
的接口,从而使得客户端能够通过Target
接口使用Adaptee
的功能。
UML 类图表示
+--------------------+ +-------------------+
| Target | | Adaptee |
+--------------------+ +-------------------+
| +request() | | +specific_request()|
+--------------------+ +-------------------+▲ ▲ | || || |
+--------------------+ +-------------------+
| Adapter | | Client |
+--------------------+ +-------------------+
| +request() | | +use_target() |
| -adaptee: Adaptee | +-------------------+
+--------------------+
适配器模式的两种形式
- 对象适配器:通过组合的方式,适配器类包含一个被适配的类的实例。
- 类适配器:通过继承的方式,适配器类同时继承目标类和被适配类。
2. 适配器模式的应用场景
适配器模式适用于以下几种情况:
- 接口不兼容的类需要协同工作:当已有的类由于接口不兼容而无法直接与系统中的其他类协同工作时,适配器模式是理想的解决方案。
- 复用已有的类,而不改变其代码:当一个类的功能符合需求,但它的接口与现有的系统不兼容时,可以通过适配器模式进行复用,而不需要修改已有类的代码。
- 使用第三方库或API:如果一个外部库或API的接口不符合当前系统的需求,可以通过适配器将其封装为符合需求的接口。
实际应用场景
- 数据库驱动适配:当使用不同数据库时,适配器模式可以将不同数据库驱动的API接口转换为统一的数据库访问接口。
- 日志系统适配:当需要将不同的日志系统统一到一个接口时,可以通过适配器模式来适配不同的日志库。
- UI适配器:在跨平台UI开发中,不同平台的UI组件接口可能不同,适配器模式可以帮助封装不同的UI组件以提供统一的接口。
3. Python 实现适配器模式
接下来,我们将通过代码来演示如何在Python中实现适配器模式。我们会以一个例子展开:假设我们有一个 Adaptee
类,它具有一个不符合当前系统需求的方法 specific_request
,我们需要通过适配器将它适配成 Target
类中的 request
方法。
3.1 对象适配器的实现
对象适配器通过组合的方式来适配不兼容的类。
定义现有类(Adaptee)
class Adaptee:def specific_request(self):return "Adaptee: Specific behavior"
定义目标接口(Target)
class Target:def request(self):pass
定义适配器类(Adapter)
适配器类将 Adaptee
的 specific_request()
方法转换为 Target
的 request()
方法。
class Adapter(Target):def __init__(self, adaptee: Adaptee):self.adaptee = adapteedef request(self):return f"Adapter: Translated {self.adaptee.specific_request()}"
客户端代码
客户端可以通过 Target
接口使用 Adaptee
的功能,而不需要直接访问 Adaptee
类。
def client_code(target: Target):print(target.request())# 使用适配器
adaptee = Adaptee()
adapter = Adapter(adaptee)
client_code(adapter)
输出:
Adapter: Translated Adaptee: Specific behavior
在这个例子中,客户端只需要使用 Target
接口,而适配器 Adapter
将 Adaptee
的接口转换为客户端期望的接口。
3.2 类适配器的实现
类适配器通过继承的方式适配 Adaptee
类和 Target
类。Python支持多重继承,因此我们可以通过继承 Adaptee
和 Target
来实现类适配器。
class ClassAdapter(Target, Adaptee):def request(self):return f"ClassAdapter: Translated {self.specific_request()}"# 使用类适配器
adapter = ClassAdapter()
client_code(adapter)
输出:
ClassAdapter: Translated Adaptee: Specific behavior
这种方式避免了组合的使用,适合在多重继承不会带来复杂性时使用。
4. 适配器模式的优缺点
优点
- 提高了类的复用性:适配器模式允许我们在不修改已有代码的情况下使用不兼容的类,从而提高代码的复用性。
- 遵循单一职责原则:通过适配器类处理接口的转换工作,使得每个类都专注于自身的职责。
- 提高了系统的灵活性:可以很容易地添加新的适配器来适配不同的类,使系统具有更高的可扩展性。
缺点
- 增加了系统的复杂性:使用适配器模式会增加额外的适配器类,这可能会使系统的结构更加复杂。
- 性能开销:适配器模式通过包装方式引入了一层额外的调用,会在一定程度上增加系统的性能开销,特别是在高频调用的场景中。
5. Python特性下的适配器模式改进
Python作为动态语言,提供了一些特性,可以简化适配器模式的实现,比如鸭子类型和装饰器。通过这些特性,可以使适配器模式的实现更加灵活。
使用鸭子类型简化适配器
Python中的鸭子类型(Duck Typing)允许我们不严格依赖类型检查,只要对象具有相应的方法就可以直接调用。因此,适配器模式在Python中可以变得更加简洁。
class Adaptee:def specific_request(self):return "Adaptee: Specific behavior"class Client:def request(self, obj):return obj.specific_request()adaptee = Adaptee()
client = Client()
print(client.request(adaptee))
在这个例子中,Client
类并不关心传入的对象是什么类型,只要它具有 specific_request
方法即可。这是一种基于行为的动态适配,不需要额外的适配器类。
使用装饰器动态适配
装饰器是Python中一种非常强大的功能,可以用来动态修改或扩展对象的行为。在适配器模式中,装饰器可以用来动态适配对象。
def adapter_decorator(func):def wrapper():return f"Adapter Decorator: Translated {func()}"return wrapperclass Adaptee:def specific_request(self):return "Adaptee: Specific behavior"adaptee = Adaptee()
adaptee.specific_request = adapter_decorator(adaptee.specific_request)
print(adaptee.specific_request())
输出:
Adapter Decorator: Translated Adaptee: Specific behavior
通过使用装饰器,我们可以动态
适配对象的方法,而无需显式定义适配器类。
6. 结论
适配器模式是一个非常有用的设计模式,尤其在需要将不兼容的类或接口组合使用的场景中。通过适配器,系统可以在不修改已有代码的情况下重用类,从而提高灵活性和可扩展性。
在Python中,适配器模式的实现可以通过对象适配、类适配、鸭子类型和装饰器等方式进行,具体选择哪种方式取决于项目的需求和复杂性。
适配器模式虽然增加了系统的结构复杂度,但在实际应用中,它有效地提高了代码的复用性和系统的扩展能力。如果你在项目中遇到了接口不兼容的问题,适配器模式可能就是你需要的解决方案。
相关文章:
【设计模式】深入理解Python中的适配器模式(Adapter Pattern)
深入理解Python中的适配器模式(Adapter Pattern) 在软件开发中,常常会遇到需要让不兼容的类或接口协同工作的问题。适配器模式(Adapter Pattern)是一种结构型设计模式,通过提供一个包装器对象,…...

RuoYi-Vue若依框架-后端设置不登陆访问(白名单)
找到SecurityConfig类 确认自己的需求 /*** anyRequest | 匹配所有请求路径* access | SpringEl表达式结果为true时可以访问* anonymous | 匿名可以访问* denyAll | 用户不能访问* fullyAuthenticated | 用户完全认证可…...
C语言初阶小练习2(三子棋小游戏的实现代码)
这是C语言小游戏三子棋的代码实现 test.c文件是用来测试的部分 game.h文件是用来声明我们说写出的函数 game.c文件是用来编写我们的功能实现函数部分 1.test.c #define _CRT_SECURE_NO_WARNINGS 1 #include"game.h" void menu() {printf("***************…...
金融行业合同管理如何利用AI技术进行风险预警?
2024年以来,金融行业的发展主线被锚定,强调了防风险的基调,尤其是系统性风险的防范。金融工作的重点在于实现六个强大:强大的货币、强大的中央银行、强大的金融机构、强大的国际金融中心、强大的金融监管、强大的金融人才队伍。这…...

世界数字农业盛宴与技术探索,25年3月聚焦世界灌溉科技大会
由中国农业节水和农村供水技术协会、中国农垦节水农业产业技术联盟、北京物联网智能技术应用协会、振威国际会展集团主办的“世界灌溉科技大会”、“第11届北京国际数字农业与灌溉技术博览会”,定于2025年3月31日至4月2日在北京国家会议中心举办。 作为世界三大灌溉…...

二百六十九、Kettle——ClickHouse清洗ODS层原始数据增量导入到DWD层表中
一、目的 清洗ClickHouse的ODS层原始数据,增量导入到DWD层表中 二、实施步骤 2.1 newtime select( select create_time from hurys_jw.dwd_statistics order by create_time desc limit 1) as create_time 2.2 替换NULL值 2.3 clickhouse输入 2.4 字段选择 2.5 …...

Maya---骨骼绑定
调节骨骼大小 回车键确认骨骼 FK子集跟父集走 IK子集不跟父集走 前视图中按shift键添加骨骼 清零、删除历史记录,创建新的物体...

携手并进,智驭教育!和鲸科技与智谱 AI 签署“101 数智领航计划”战略合作协议
近日,上海和今信息科技有限公司(以下简称“和鲸科技”)与北京智谱华章科技有限公司(以下简称“智谱 AI”)签署“101 数智领航计划”战略合作协议。双方将携手营造智能化学科教育与科研环境,提供多种大模型工…...
牛客周赛63
https://ac.nowcoder.com/acm/contest/91592 好数 简单的判断两位数,且十位等于个位 #include <bits/stdc.h> #define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); #define int long long using namespace std; using ll long long; using pii …...
git restore恢复删除文件
新版本 在 Git 2.23 版本之后,Git 引入了一个新的命令 git restore,用于简化文件恢复操作。可以用 git restore 来恢复误删除的文件。下面是详细的使用方法: 1. 恢复工作区中删除的文件(未提交) 如果文件已被删除&a…...

MacOS13虚拟机VMware Workstation Pro 16安装
资源 安装unlocker 安装虚拟机 低版本的还没有MacOS13选项,这也是我安装低版本虚拟机踩过的坑 找个教程安装就可以了 省略…自己去找找教程… 过程中我使用桥接是不行的,没有网络,后面重新下一步一步的选择默认的网络重装后就好了&am…...
docker 数据管理,数据持久化详解 一
docker镜像是分层设计的,镜像出只读,通过镜像启动的容器添加一层可读写的文件系统,用户写入的数据表都保存在这层中。 容器的数据分层目录 LowerDir:image 镜像层,即镜像本身,制度 UpperDir:容…...

【ios】使用TestFlight将app分发给测试人员(超详细)
我的环境: macos系统是Ventura 13.0 xcode是14.2(后面发现至少需要15版本的xcode才能上传app) 证书生成 可以通过xcode生成Distribution类型的证书,如果你已经有的话那就忽略,这个证书也是备案时所需的。 我是已…...

证件照小程序源码,前后端稳定运行
演示:证寸照制作 运行环境: Linux Nginx PHP >5.6 MySQL>5.6 安装步骤: 1.下载源码上传至你的服务器宝塔面板 2.直接添加站点选择源码目录,新建数据库 3.设置代码执行目录为/web 4.在浏览器中输入你的域名,会提示安装,填写…...
java白嫖同事的从身份证里面提取省市区地址详细信息的工具类代码
/*** author sunpeiyang* date 2024/10/21 16:35*/ Slf4j public class MiTaAddressExtractor {/*** 获取详细地址** param fullAddress 身份证完整地址*/public static String getDetailedAddress(String fullAddress) {String[] addressArrays spliceDetailedAddress(fullAd…...
计算机网络基本架构示例2
一、企业内部网络架构 在一个中型企业中,通常会有以下的网络架构: - 核心层:由高性能的核心交换机组成,负责快速转发大量数据。例如采用具有高带宽和冗余功能的三层交换机,确保整个网络的稳定运行。它连接着各个部门的…...

无人机之室内定位技术篇
无人机的室内定位技术是实现无人机在室内环境中精准导航和定位的关键技术。由于室内环境复杂,卫星导航系统(如GPS)无法提供有效的信号,因此需要依赖其他室内定位技术。 一、主要技术类型 基于视觉的定位技术 原理:利…...
在ubuntu20.04中输入不存在shell命令时,报错ModuleNotFoundError的解决方案
这个问题出现过好几次,每次都比较困扰,以下的解决方案比较适合: 当我输入ubuntu无法识别的命令的时候,正常来说应该提示类似于 command not found 之类的字眼,但是系统确报了如下错误: Traceback (most r…...

互联网语言 互联网开发 互联网架构
JAVA和PHP是两种广泛应用于互联网开发的编程语言,它们在多个维度上展现出显著的不同。 JAVA是一种面向对象的编程语言,以其严谨、高效的特性而著称。JAVA的语法结构复杂且规范,强调封装、继承和多态等面向对象原则,适合构建大型企…...
解决MybatisPlus updateById更新数据时将没传的数据也更新成了null
首先,MybatisPlus在调用自带的更新接口updateById时,如果没加任何配置,默认是不会将前端没传的数据也更新成null的。即MyBatisPlus不会更新传入实体中为null的字段,只会更新设置了不为null的值。 如果发现没传的也更新成null了的话…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...

微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...

均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...

基于TurtleBot3在Gazebo地图实现机器人远程控制
1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...

接口自动化测试:HttpRunner基础
相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具,支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议,涵盖接口测试、性能测试、数字体验监测等测试类型…...