【再谈设计模式】适配器模式 ~接口兼容的桥梁
一、引言
在软件开发的复杂世界里,不同的组件、类或者系统往往有着各自独立的设计和接口定义。当需要将这些原本不兼容的部分整合在一起协同工作时,就像尝试将方形的榫头插入圆形的卯眼一样困难。适配器设计模式就如同一位神奇的工匠,能够巧妙地解决这个问题,让不同接口之间实现无缝对接。
二、定义与描述
适配器设计模式属于结构型设计模式。它的主要作用是将一个类的接口转换为另一个接口,使原本由于接口不兼容而不能一起工作的类能够协同工作。可以把适配器想象成一个中间件,它包裹着一个已有的类,对外提供一个符合目标需求的新接口。
三、抽象背景
在大型软件项目中,往往会集成多个不同的库或者模块。这些模块可能是由不同的团队开发,或者是在不同的时期基于不同的需求开发的。每个模块都有自己的接口设计,当需要将它们组合使用时,就会出现接口不匹配的情况。例如,一个旧的数据库访问模块可能提供了一种特定的查询接口,而新的业务逻辑层需要一种不同格式的查询结果。这时候就需要适配器来协调两者之间的差异。
四、适用场景与现实问题解决
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的基本使用指南: 拖拽…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...

Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...

Elastic 获得 AWS 教育 ISV 合作伙伴资质,进一步增强教育解决方案产品组合
作者:来自 Elastic Udayasimha Theepireddy (Uday), Brian Bergholm, Marianna Jonsdottir 通过搜索 AI 和云创新推动教育领域的数字化转型。 我们非常高兴地宣布,Elastic 已获得 AWS 教育 ISV 合作伙伴资质。这一重要认证表明,Elastic 作为 …...

【无标题】湖北理元理律师事务所:债务优化中的生活保障与法律平衡之道
文/法律实务观察组 在债务重组领域,专业机构的核心价值不仅在于减轻债务数字,更在于帮助债务人在履行义务的同时维持基本生活尊严。湖北理元理律师事务所的服务实践表明,合法债务优化需同步实现三重平衡: 法律刚性(债…...