【再谈设计模式】适配器模式 ~接口兼容的桥梁
一、引言
在软件开发的复杂世界里,不同的组件、类或者系统往往有着各自独立的设计和接口定义。当需要将这些原本不兼容的部分整合在一起协同工作时,就像尝试将方形的榫头插入圆形的卯眼一样困难。适配器设计模式就如同一位神奇的工匠,能够巧妙地解决这个问题,让不同接口之间实现无缝对接。

二、定义与描述
适配器设计模式属于结构型设计模式。它的主要作用是将一个类的接口转换为另一个接口,使原本由于接口不兼容而不能一起工作的类能够协同工作。可以把适配器想象成一个中间件,它包裹着一个已有的类,对外提供一个符合目标需求的新接口。

三、抽象背景

在大型软件项目中,往往会集成多个不同的库或者模块。这些模块可能是由不同的团队开发,或者是在不同的时期基于不同的需求开发的。每个模块都有自己的接口设计,当需要将它们组合使用时,就会出现接口不匹配的情况。例如,一个旧的数据库访问模块可能提供了一种特定的查询接口,而新的业务逻辑层需要一种不同格式的查询结果。这时候就需要适配器来协调两者之间的差异。
四、适用场景与现实问题解决
1、适用场景
集成第三方库
当使用第三方库时,其接口可能与项目中的其他部分不兼容。例如,一个图形绘制库的坐标系统与项目中自定义的坐标系统不同,通过适配器可以将两者协调起来。
旧系统升级
在对旧系统进行升级时,新的模块可能采用了新的接口标准。使用适配器模式可以让旧系统中的部分继续使用,而不必对旧系统进行大规模的重写。
多平台适配

对于需要在不同平台(如Windows、Linux、Mac)上运行的软件,不同平台可能有不同的API。适配器可以将不同平台的API转换为统一的接口,使业务逻辑层能够在不同平台上无缝运行。
2、现实问题解决
假设一个公司收购了另一家公司,被收购公司有一套已经开发好的用户认证系统。收购公司的主系统有自己的用户认证接口,通过适配器模式,可以将被收购公司的用户认证系统适配到收购公司的主系统中,避免重新开发用户认证功能,节省时间和成本。
五、现实生活的例子

1、电源适配器
不同国家的电源插座标准不同,如中国的插座是扁头的,而一些国外的电器插头可能是圆头的。电源适配器就起到了接口转换的作用,它可以将国内的电源接口转换为适合国外电器使用的接口,反之亦然。
2、手机充电器转接头
新的手机可能采用了新的充电接口标准,但是旧的充电器仍然可以使用,只需要一个转接头(适配器),将旧充电器的接口转换为新手机能够接受的接口。

六、初衷与问题解决

初衷是为了提高软件的可复用性和灵活性。在面对接口不兼容的情况时,不必修改原有的类或模块,通过适配器可以快速地解决接口匹配问题,降低了代码的耦合度,使得系统更容易维护和扩展。
七、代码示例

Java示例
// 目标接口
interface Target {void request();
}// 被适配的类
class Adaptee {public void specificRequest() {System.out.println("Adaptee's specific request");}
}// 适配器类
class Adapter implements Target {private Adaptee adaptee;public Adapter(Adaptee adaptee) {this.adaptee = adaptee;}@Overridepublic void request() {adaptee.specificRequest();}
}public class Main {public static void main(String[] args) {Adaptee adaptee = new Adaptee();Target target = new Adapter(adaptee);target.request();}
}
C++示例
#include <iostream>// 目标类(抽象类)
class Target {
public:virtual void request() = 0;virtual ~Target() {}
};// 被适配的类
class Adaptee {
public:void specificRequest() {std::cout << "Adaptee's specific request" << std::endl;}
};// 适配器类
class Adapter : public Target {
private:Adaptee* adaptee;
public:Adapter(Adaptee* adaptee) : adaptee(adaptee) {}void request() override {adaptee->specificRequest();}~Adapter() {delete adaptee;}
};int main() {Adaptee* adaptee = new Adaptee();Target* target = new Adapter(adaptee);target.request();delete target;return 0;
}
Python示例
# 目标接口
class Target:def request(self):pass# 被适配的类
class Adaptee:def specific_request(self):print("Adaptee's specific request")# 适配器类
class Adapter(Target):def __init__(self, adaptee):self.adaptee = adapteedef request(self):self.adaptee.specific_request()if __name__ == "__main__":adaptee = Adaptee()target = Adapter(adaptee)target.request()
Go示例
package mainimport "fmt"// 目标接口
type Target interface {request()
}// 被适配的类
type Adaptee struct{}func (a *Adaptee) specificRequest() {fmt.Println("Adaptee's specific request")
}// 适配器结构体
type Adapter struct {adaptee *Adaptee
}func (a *Adapter) request() {a.adaptee.specificRequest()
}func main() {adaptee := &Adaptee{}target := &Adapter{adaptee: adaptee}target.request()
}
八、适配器设计模式的优缺点

优点
提高了代码的复用性
可以复用现有的类,而不需要修改它们的代码。通过适配器将其适配到新的接口下,就可以在新的场景中使用。
降低了代码的耦合度
被适配的类和使用适配后接口的类之间不需要直接交互,它们通过适配器进行通信。这样,当其中一方发生变化时,只要适配器的逻辑不变,另一方就不需要修改。
灵活性好
可以很容易地替换适配器或者被适配的类,只要遵循相应的接口规范。
缺点
增加了代码的复杂性
如果过多地使用适配器模式,会使得代码结构变得复杂,增加了理解和维护的难度。因为需要理解适配器、被适配的类以及目标接口之间的关系。
可能会降低性能
由于适配器在中间做了一层转换,可能会对性能产生一定的影响,尤其是在对性能要求极高的场景下。
九、适配器设计模式的升级版
双向适配器

普通的适配器是单向的,即从被适配的类转换到目标接口。双向适配器则可以实现双向的转换,既能将被适配类转换为目标接口,也能将符合目标接口的对象转换为被适配类的接口。例如,在两个不同的库之间,不仅要让A库能在B库的接口下工作,也要让B库能在A库的接口下工作,就可以使用双向适配器。
对象适配器和类适配器的混合使用

在某些复杂的场景下,可以结合对象适配器(使用对象组合来实现适配)和类适配器(使用继承来实现适配)的优点。例如,先通过类适配器继承一些基本的功能,再通过对象组合来实现更灵活的适配。这种混合方式可以根据具体的需求,在代码复用性、灵活性和性能之间取得更好的平衡。
相关文章:
【再谈设计模式】适配器模式 ~接口兼容的桥梁
一、引言 在软件开发的复杂世界里,不同的组件、类或者系统往往有着各自独立的设计和接口定义。当需要将这些原本不兼容的部分整合在一起协同工作时,就像尝试将方形的榫头插入圆形的卯眼一样困难。适配器设计模式就如同一位神奇的工匠,能够巧妙…...
使用Cursor和Claude AI打造你的第一个App
大家好,使用Cursor和Claude AI打造应用程序是一个结合智能代码辅助和人工智能对话的创新过程。Cursor是一个编程辅助工具,它通过智能代码补全、聊天式AI对话和代码生成等功能,帮助开发者提高编程效率。Claude AI则是一个强大的人工智能平台&a…...
粗读Apache Paimon 的基本概念及其组成结构
文章目录 一、Paimon的基本概念(一)快照(二)分区(三)分桶(四)一致性保证 二、Paimon的组成结构(一)文件布局(二)存储结构(…...
c++调用 c# dll 通过 P/Invoke (详细避坑)
项目场景: VS2022 .NET8 , 项目应用的库需要支持AOT,不支持AOT的库看这里 我的c项目很奇怪,如果使用 clr 调用c# dll,会有很多报错,所以使用 P/Invoke方法,这个方法不会有任何奇怪的报错 解决方案 示例…...
李春葆《数据结构》——图相关代码
邻接矩阵结构体: #define MAX<最大结点个数> #define INF 32765 //定义无穷 typedef struct{int no;//顶点的编号;InfoType info;//顶点的其他信息 }vertexType;//顶点的类型 typedef struct{int edges[MAX][Max];//邻接矩阵数组 int vertexTy…...
Linux驱动开发第2步_“物理内存”和“虚拟内存”的映射
“新字符设备的GPIO驱动”和“设备树下的GPIO驱动”都要用到寄存器地址,使用“物理内存”和“虚拟内存”映射时,非常不方便,而pinctrl和gpio子系统的GPIO驱动,非常简化。因此,要重点学习pinctrl和gpio子系统下的GPIO驱…...
告别多品牌乱战,吉利开始觉醒
科技新知 原创作者丨思原 编辑丨蕨影 2007年,是国内自主品牌汽车萌芽的一年,当时行业普遍奉行“多生孩子好打架”战略,吉利也是在这样的背景下发布了《宁波宣言》,奠定了之后十多年的发展主导思想。 然而,新能源的快…...
Target-absent Human Attention
Abstract 预测人类注视行为对于构建能够预测用户注意力的人机交互系统非常重要。已经开发出计算机视觉模型来预测人们在搜索目标物体时的注视点。但当目标不存在于图像中时,又该如何处理呢?同样重要的是要了解当人们找不到目标时,他们如何进行搜索,以及何时停止搜索。在本文…...
<QNAP 453D QTS-5.x> 日志记录:在 Docker 中运行的 Flask 应用安装 自签名 SSL 证书 解决 Chrome 等浏览器证书安全
原因:Chrome 不信任 ssc 证书 使启用了 HTTPS,即使有使用 自签名证书 (self-signed certificate 非由可信的证书颁发机构 【CA,Certificate Authority】签发的)。浏览器 Chrome 默认不信任自签名证书,也会报 NET::ERR_…...
通过huggingface-cli下载Hugging Face上的公开数据集或模型至本地
1. 获取 Access Tokens 在使用huggingface-cli命令下载之前需要先去官网获取 Access Tokens: 获取tokens的官网链接:https://huggingface.co/settings/tokens点击新增 token: 然后选择 write 权限: 最后,这个 Access…...
论文阅读——Intrusion detection systems using longshort‑term memory (LSTM)
一.基本信息 论文名称:Intrusion detection systems using longshort‑term memory (LSTM) 中文翻译:基于长短期记忆(LSTM)的入侵检测系统 DOI:10.1186/s40537-021-00448-4 作者:FatimaEzzahra Laghrissi1* , Samira Douzi2*, Kha…...
SparkSQL的执行过程:从源码角度解析逻辑计划、优化计划和物理计划
SparkSQL的执行过程可以分为以下几个阶段:从用户的SQL语句到最终生成的RDD执行,涵盖逻辑计划、优化计划和物理计划。以下是详细的源码角度解析: 1. 解析阶段(Parsing) SQL语句解析:Spark 使用 Catalyst 引…...
Leetcode打卡:新增道路查询后的最短距离II
执行结果:通过 题目:3244 新增道路查询后的最短距离II 给你一个整数 n 和一个二维整数数组 queries。 有 n 个城市,编号从 0 到 n - 1。初始时,每个城市 i 都有一条单向道路通往城市 i 1( 0 < i < n - 1&…...
Spring Web入门练习
加法计算器 约定前后端交互接⼝ 约定 "前后端交互接⼝" 是进⾏ Web 开发中的关键环节. 接⼝⼜叫 API(Application Programming Interface), 我们⼀般讲到接⼝或者 API,指的都是同⼀个东西. 是指应⽤程序对外提供的服务的描述, ⽤于交换信息…...
计算机毕业设计 | SpringBoot+vue汽车资讯网站 汽车购买咨询管理系统(附源码+论文)
1,绪论 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及,互联网成为人们查找信息的重要场所,二十一世纪是信息的时代,所以信息的管理显得特别重要。因此,使用计算机来管理汽车资讯网站的相关信息成为必然…...
stm32下的ADC转换(江科协 HAL版)
十二. ADC采样 文章目录 十二. ADC采样12.1 ADC的采样原理12.2 STM32的采样基本过程1.引脚与GPIO端口的对应关系2.ADC规则组的四种转换模式(**)2.2 关于转换模式与配置之间的关系 12.3 ADC的时钟12.4 代码实现(ADC单通道 & ADC多通道)1. 单通道采样2. 多通道采样 19.ADC模数…...
解决IntelliJ IDEA的Plugins无法访问Marketplace去下载插件
勾选Auto-detect proxy setting并填入 https://plugins.jetbrains.com 代理URL,可以先做检查连接:...
react 如何修改弹出的modal的标题
原来标题的样子: 修改为: 实现方式: <Modal title<span>股价趋势/{this.state.pccode}</span> visible{this.state.isPriceModalOpen} style{{ top: 20 }} width{1320} height{400} footer{null} onCancel{()>this.hideMo…...
C#中的二维数组的应用:探索物理含义与数据结构的奇妙融合
在C#编程中,二维数组(或矩阵)是一种重要的数据结构,它不仅能够高效地存储和组织数据,还能通过其行、列和交叉点(备注:此处相交处通常称为“元素”或“单元格”,代表二维数组中的一个…...
HTML5拖拽API学习 托拽排序和可托拽课程表
文章目录 前言拖拽API核心概念拖拽式使用流程例子注意事项综合例子🌰 可拖拽课程表拖拽排序 前言 前端拖拽功能让网页元素可以通过鼠标或触摸操作移动。HTML5 提供了标准的拖拽API,简化了拖放操作的实现。以下是拖拽API的基本使用指南: 拖拽…...
从‘画图’到‘造芯’:模拟版图工程师必须懂的CMOS工艺那些事儿
从‘画图’到‘造芯’:模拟版图工程师必须懂的CMOS工艺那些事儿 当你第一次打开PDK文档,面对密密麻麻的设计规则表格时,是否感觉像在解读天书?作为模拟版图工程师,我们每天都在与纳米级的几何图形打交道,但…...
桶排序:分布式排序的高效实现
桶排序:分布式排序的高效实现 算法原理 核心思路 桶排序是一种分布式排序算法,其核心思想是: 将待排序的数据分到有限数量的桶里每个桶再分别进行排序(可以使用其他排序算法)最后将各个桶中的数据有序地合并起来 复杂度…...
3大核心功能让你轻松掌握League-Toolkit英雄联盟辅助工具
3大核心功能让你轻松掌握League-Toolkit英雄联盟辅助工具 【免费下载链接】League-Toolkit 兴趣使然的、简单易用的英雄联盟工具集。支持战绩查询、自动秒选等功能。基于 LCU API。 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit League-Toolkit是一款基…...
League-Toolkit:基于LCU API的英雄联盟智能辅助工具
League-Toolkit:基于LCU API的英雄联盟智能辅助工具 【免费下载链接】League-Toolkit 兴趣使然的、简单易用的英雄联盟工具集。支持战绩查询、自动秒选等功能。基于 LCU API。 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit 在快节奏的MOBA游…...
避坑指南:运行YooAsset 2.3.9官方Demo时,你可能会遇到的Sprite白块和退出报错
避坑指南:YooAsset 2.3.9官方Demo运行时的Sprite白块与退出报错深度解析 当Unity开发者初次接触YooAsset资源管理系统时,官方Demo往往是快速上手的最佳途径。然而在YooAsset 2.3.9版本的示例项目中,不少开发者反馈遇到了两个典型问题&#x…...
3步终极解放QQ音乐加密文件:QMCDecode全平台播放攻略
3步终极解放QQ音乐加密文件:QMCDecode全平台播放攻略 【免费下载链接】QMCDecode QQ音乐QMC格式转换为普通格式(qmcflac转flac,qmc0,qmc3转mp3, mflac,mflac0等转flac),仅支持macOS,可自动识别到QQ音乐下载目录,默认转…...
避开C盘爆满!保姆级教程:在D盘安装Unity 2023.2f1c1和VS2022社区版
避开C盘爆满!保姆级教程:在D盘安装Unity 2023.2f1c1和VS2022社区版 对于刚接触游戏开发的新手来说,安装Unity和Visual Studio往往是遇到的第一个"拦路虎"。更让人头疼的是,这两个"重量级"开发工具默认都会占…...
PyLink 实战技巧:从基础连接到高级调试
1. PyLink入门:从零搭建调试环境 第一次接触PyLink时,我也被各种专业术语弄得晕头转向。后来才发现,只要掌握几个关键步骤,就能快速搭建起嵌入式调试环境。PyLink本质上是个Python库,它像翻译官一样,把我们…...
超好看的Win10音量控制工具Eartrumpet
链接:https://pan.quark.cn/s/48beeba09372Eartrumpe是一款非常好用的系统音量控制工具,可以针对不同的应用进行音量控制,让你同时播放多个音频,在打游戏的时候可以调小游戏声音播放音乐,有需要的朋友欢迎下载使用&…...
RVC模型计算机组成原理视角:理解AI推理的硬件底层
RVC模型计算机组成原理视角:理解AI推理的硬件底层 你是不是觉得AI模型推理就像一个黑盒子?输入一段音频,点一下按钮,等一会儿,就得到了变声后的结果。整个过程看似简单,但背后却是一场在GPU硬件上精密上演…...
