适配器模式(Adapter)
适配器模式用于将一个接口转换成用户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。
Adapter is a structural design pattern that transforms an interface into another interface for the users' desires
and allows objects with incompatible interfaces to collaborate.
结构设计
适配器模式包含如下角色:
Target:目标类,描述了其他类与客户端代码合作时必须遵循的协议,简单来说,就是客户端使用的目标接口。
Adaptee:适配者类,待适配的类。客户端与其接口不兼容,因此无法直接调用其功能。
Adapter:适配器类,适配器(Adapter)是一个可以同时与客户端和服务交互的类:它在实现客户端接口的同时封装了服务对象。适配器接受客户端通过适配器接口发起的调用,并将其转换为适用于被封装服务对象的调用。
Client:客户端类,客户端代码只需通过接口与适配器交互即可, 无需与具体的适配器类耦合。 因此,开发者可以向程序中添加新类型的适配器而无需修改已有代码。这在服务类的接口被更改或替换时很有用:开发者无需修改客户端代码就可以创建新的适配器类。适配器模式有对象适配器和类适配器两种实现:
(1) 对象适配器:

(2) 类适配器:

伪代码实现
接下来将使用代码介绍下适配器模式的实现。首先是对象适配器模式的实现:
// 1、目标类,对客户端需要使用的目标接口进行声明
public interface Target {void request();
}// 2、适配者类,待适配类,其声明的接口无法被客户端直接调用
public class Adaptee {public void specialRequest() {System.out.println("---------do some thing in an adaptee instance---------");}
}// 3、适配器类,适配器可以接受客户端通过适配器接口发起的调用,并将其转换为适用于被封装服务对象的调用。
// 对象适配器通过组合适配者实例并实现目标类来完成适配
public class Adapter implements Target {private Adaptee adaptee = new Adaptee();@Overridepublic void request() {adaptee.specialRequest();}
}// 4、客户端调用
public class AdapterClient {public void test() {Target adapter = new Adapter();adapter.request();}
}
其次是类适配器模式的实现:
// 1、目标类,对客户端需要使用的目标接口进行声明
public interface Target {void request();
}// 2、适配者类,待适配类,其声明的接口无法被客户端直接调用
public class Adaptee {public void specialRequest() {System.out.println("---------do some thing in an adaptee instance---------");}
}// 3、适配器类,适配器可以接受客户端通过适配器接口发起的调用,并将其转换为适用于被封装服务对象的调用。
// 类适配器通过继承适配者实例并实现目标类来完成适配
public class Adapter extends Adaptee implements Target {@Overridepublic void request() {specialRequest();}
}// 4、客户端调用
public class AdapterClient {public void test() {Target adapter = new Adapter();adapter.request();}
}
从上面的实现不难发现,类适配器是基于继承实现,而对象适配器是基于组合关系实现。由于对象适配器是通过关联关系进行耦合的,因此在设计时更灵活,而类适配器就只能通过重写Adaptee的方法进行扩展。
适用场景
在以下情况下可以考虑使用适配器模式:
(1) 需要使用某个现有类,但是这些类的接口不符合系统的需要,可以考虑使用适配器。如以下场景:
适配器模式允许创建一个中间层类, 其可作为代码与遗留类、第三方类或提供接口的类之间的转换器。
如果需要复用这样一些类, 他们处于同一个继承体系, 并且他们又有了额外的一些共同的方法, 但是这些共同的方法不是所有在这一继承体系中的子类所具有的共性。
扩展每个子类,将缺少的功能添加到新的子类中,且无法将功能提取到父类。 但是, 必须在所有新子类中重复添加这些代码,这样会使得代码有坏味道。
(2) 想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类一起工作,可以考虑使用适配器。
(3) 将缺失功能添加到一个适配器类中是一种优雅的解决方案。 在这方案中,开发者可以将缺少功能的对象封装在适配器中, 从而动态地获取所需功能。 如要这一点正常运作, 目标类必须要有通用接口, 适配器的成员变量应当遵循该通用接口。 这种方式同装饰模式非常相似。
优缺点
适配器让接口不兼容的对象可以相互合作。适配器模式有以下优点:
(1) 单一职责。可以将接口或数据转换代码从程序主要业务逻辑中分离。
(2) 将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,而无须修改原有代码。
(3) 增加了类的透明性和复用性,将具体的实现封装在适配者类中,对于客户端来说是透明的,而且提高了适配者的复用性。
(4) 灵活性和扩展性都非常好,通过使用配置文件,可以很方便地更换适配器,也可以在不修改原有代码的基础上增加新的适配器类,完全符合“开闭原则”。
类适配器模式还具有如下优点:
由于适配器类是适配者类的子类,因此可以在适配器类中置换一些适配者的方法,使得适配器的灵活性更强。
对象适配器模式还具有如下优点:
一个对象适配器可以把多个不同的适配者适配到同一个目标,也就是说,同一个适配器可以把适配者类和它的子类都适配到目标接口。
但是适配器模式也存在以下缺点:
(1) 代码整体复杂度增加, 因为开发者需要新增一系列接口和类。 有时直接更改服务类使其与其他代码兼容会更简单。
类适配器模式还具有如下缺点:
对于Java、C#等不支持多重继承的语言,一次最多只能适配一个适配者类,而且目标抽象类只能为抽象类,不能为具体类,其使用有一定的局限性,不能将一个适配者类和它的子类都适配到目标接口。
对象适配器模式还具有如下缺点:
与类适配器模式相比,要想置换适配者类的方法就不容易。如果一定要置换掉适配者类的一个或多个方法,就只好先做一个适配者类的子类,将适配者类的方法置换掉,然后再把适配者类的子类当做真正的适配者进行适配,实现过程较为复杂。
参考
《设计模式:可复用面向对象软件的基础》 Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides 著 李英军, 马晓星 等译
https://design-patterns.readthedocs.io/zh_CN/latest/structural_patterns/adapter.html 适配器模式
https://blog.csdn.net/ShuSheng0007/article/details/116161690 秒懂设计模式之适配器模式
https://www.runoob.com/design-pattern/adapter-pattern.html 适配器模式
https://www.cnblogs.com/adamjwh/p/9033549.html 简说设计模式——适配器模式
https://refactoringguru.cn/design-patterns/adapter 适配器模式
相关文章:
适配器模式(Adapter)
适配器模式用于将一个接口转换成用户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。 Adapter is a structural design pattern that…...
Spring学习笔记——1
Spring学习笔记——1 一、Spring入门1.1、学习路线1.2、传统Javaweb开发困惑及解决方法1.3、三种思想的提出和框架概念1.3.1、IoC、DI和AOP思想提出1.3.2、框架的基本特点 1.4、Spring概述1.5、BeanFactory快速入门1.6、ApplicationContext快速入门1.7、BeanFactory与Applicati…...
leetcode 406. 根据身高重建队列
2023.8.2 这题一开始有点让人懵逼的是有两个维度,一个是身高,还一个是前面人高于自己的人数。这种题一般需要先固定一个维度,再去确定另外一个维度,不要想着兼顾。 经过纸上模拟,我的思路是先通过身高进行从大到小排序…...
Matlab实现AGNES算法
在数据分析和机器学习中,聚类是一种常用的无监督学习方法,它可以将数据点按照某种相似度标准进行分组,从而发现数据中的结构和模式。聚类算法有很多种,其中一种比较经典的是AGNES算法,它是一种基于层次的聚类算法&…...
STM32F4_外部SRAM
目录 前言 1. SRAM控制原理 1.1 SRAM功能框图 1.2 SRAM读写时序 2. FSMC简介 2.1 FSMC架构 2.2 FSMC地址映射 2.3 FSMC控制SRAM时序 3. FSMC结构体 4. 库函数配置FSMC 5. 实验程序 5.1 main.c 5.2 SRAM.c 5.3 SRAM.h 前言 STM32F4自带了192K字节的SRAM࿱…...
Java的代理模式
java有三种代理模式 静态代理 jdk动态代理 cglib实现动态代理 代理模式的定义: 为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的…...
FilterAttributeOnClassMethod
目录 1 BadMethodFilterAttribute 2 FilterAttributeOnClassMethod 2.1 OnMethodExecuted 2.2 OnMethodExecutedAsync 2.3 OnMethodExecuting BadMethodFilterAttribute using System; using System.Threading.Tasks; namespace Flatwhite.Core.Tests.Attributes …...
springboot + (mysql/pgsql) + jpa 多数据源(不同类数据源)
配置文件: spring:datasource:primary:jdbc-url: jdbc:mysql://host:3306/数据库?useUnicodetrue&characterEncodingUTF-8&autoReconnecttrue&failOverReadOnlyfalse&serverTimezoneAsia/Shanghai&zeroDateTimeBehaviorconvertToNullusername…...
【Golang】Golang进阶系列教程--Go 语言 context 都能做什么?
文章目录 前言核心是 Context 接口:包含四个方法:遵循规则WithCancelWithDeadlineWithTimeoutWithValue 前言 很多 Go 项目的源码,在读的过程中会发现一个很常见的参数 ctx,而且基本都是作为函数的第一个参数。 为什么要这么写呢…...
画图干货!14种uml图类型及示例
1. 什么是 UML UML 是统一建模语言的缩写。UML 图是基于 UML(统一建模语言)的图表,目的是直观地表示系统及其主要参与者、角色、动作、工件或类,以便更好地理解、更改、维护或记录信息关于系统。简而言之,UML 是一种…...
计算机视觉实验:人脸识别系统设计
实验内容 设计计算机视觉目标识别系统,与实际应用有关(建议:最终展示形式为带界面可运行的系统),以下内容选择其中一个做。 1. 人脸识别系统设计 (1) 人脸识别系统设计(必做):根据…...
振弦采集仪完整链条的岩土工程隧道安全监测
振弦采集仪完整链条的岩土工程隧道安全监测 隧道工程是一种特殊的地下工程,其建设过程及运行期间,都受到各种内外力的作用,如水压、地震、地质变形、交通荷载等,这些因素都会对隧道的安全性产生影响。因此,对隧道的安…...
NLP实战9:Transformer实战-单词预测
目录 一、定义模型 二、加载数据集 三、初始化实例 四、训练模型 五、评估模型 🍨 本文为[🔗365天深度学习训练营]内部限免文章(版权归 *K同学啊* 所有) 🍖 作者:[K同学啊] 模型结构图: &a…...
使用Vue.js和Rust构建高性能的物联网应用
物联网(IoT)应用是现代技术的重要组成部分,它们可以在各种场景中(例如智能家居,工业自动化等)提供无缝的自动化解决方案。在这篇文章中,我们将探讨如何使用Vue.js和Rust构建高性能的物联网应用。 1. 为什么选择Vue.js…...
idea调节文字大小、日志颜色、git改动信息
idea调节菜单栏文字大小: 调节代码文字大小: 按住ctrl滚动滑轮可以调节代码文字大小: 单击文件即可在主窗口上打开显示: idea在控制台对不同级别的日志打印不同颜色 : “grep console”插件 点击某一行的时候&#x…...
避免大龄程序员边缘化:如何在技术行业中保持竞争力
目录 导语持续学习和进修维护专业形象寻找适合自己的领域构建个人品牌和网络拥抱变化和创新实例结语: 导语 导语:随着科技的不断发展,技术行业的竞争日益激烈。对于那些年龄稍长的程序员来说,如何保持竞争力并避免边缘化成为了一…...
Jenkins工具系列 —— 启动 Jenkins 服务报错
错误显示 apt-get 安装 Jenkins 后,自动启动 Jenkins 服务报错。 排查原因 直接运行jenkins命令 发现具体报错log:Failed to start Jetty或Failed to bind to 0.0.0.0/0.0.0.0:8080或Address already in use 说明:这里提示的是8080端口号…...
华为数通HCIA-实验环境ensp简介
ensp 路由器:AR系列、NE系列; 模拟器中使用AR2220; 交换机:S系列、CE系列; 模拟器中使用S5700; 线缆:copper——以太网链路; serial——串行链路,在模拟器中用于模…...
SK5代理与IP代理:网络安全中的爬虫利器
一、什么是IP代理与SK5代理? IP代理: IP代理是一种允许用户通过代理服务器进行网络连接的技术。用户请求经由代理服务器中转,从而实现隐藏真实IP地址,保护用户隐私,并在一定程度上突破IP访问限制。常见的IP代理有HTTP…...
实战:Prometheus+Grafana监控Linux服务器及Springboot项目
文章目录 前言知识积累什么是Prometheus什么是Grafana怎样完成数据采集和监控 环境搭建docker与docker-compose安装docker-compose编写 监控配置grafana配置prometheus数据源grafana配置dashboardLinux Host Metrics监控Spring Boot 监控 写在最后 前言 相信大家都知道一个项目…...
CANN/PyPTO精度调试指南
精度调试 【免费下载链接】pypto PyPTO(发音: pai p-t-o):Parallel Tensor/Tile Operation编程范式。 项目地址: https://gitcode.com/cann/pypto 简介 当PyPTO算子执行后无功能告警或报错,但输出数据不符合预期时&#x…...
在RK3568开发板上搭建NFS服务器:打通ARM与X86文件共享
1. 项目概述:为什么要在RK3568上折腾NFS?手头有一块瑞芯微RK3568的开发板,性能不错,四核A55的架构,跑个轻量级服务器绰绰有余。最近在做一个边缘计算相关的原型验证,需要在开发板和我的主力工作站之间频繁地…...
龙芯LS2K PMON启动全解析:从内核到U盘识别的奥秘
【龙芯LS2K PMON终极干货】整机设备启动全景图:从 mainbus 开机到 U 盘识别全流程 一、整篇总纲(最强一句话) 内核启动 → 读 ioconf.c/cfdata 硬件族谱 → 从根总线 mainbus 开始遍历 → 逐级 attach 设备 → 启动 PCI → 扫描到 OTG 控制器 → 加载 dwc2 驱动 → 开启 U…...
2026年企业AI落地新趋势!RAG知识库实战指南:环境搭建到生产部署全解析
本文介绍了RAG(检索增强生成)技术在企业知识库中的应用,通过从环境搭建到生产部署的完整实战指南,阐述如何利用RAG提升大语言模型回答的准确性、可追溯性和时效性。文章涵盖了基础环境配置、技术选型、数据准备、知识库构建、RAG系…...
十三张扑克APP
能开发十三张扑克APP的请联系我,有客户渠道需要这类APP,要开发很多款十三张...
别再折腾超级密码了!2024年电信光猫改桥接,打这个电话最快(附完整话术)
2024年电信光猫改桥接最省心方案:一通电话搞定全流程 去年帮邻居调试网络时,发现一个有趣的现象——十个尝试自己破解光猫超级密码的用户里,有九个会卡在第一步。不是密码失效就是界面改版,最后不得不求助运营商。这让我意识到&am…...
vue3+python基于Django框架的铁路博物馆展览系统的设计与实现67350649
目录同行可拿货,招校园代理 ,本人源头供货商项目背景技术栈核心功能模块关键技术实现部署方案项目亮点项目技术支持源码获取详细视频演示 :同行可合作点击我获取源码->->进我个人主页-->获取博主联系方式同行可拿货,招校园代理 ,本人源头供货商 项目背景 …...
跨国分布式团队协作实录:时区差不是最大障碍,信任才是
一、跨越时区:测试协作的“隐形战场”在全球化软件交付的浪潮中,跨国分布式测试团队早已成为行业标配。当上海的测试工程师迎着朝阳开始一天的工作时,旧金山的同事正披着夜色结束任务;当柏林团队在梳理测试用例,班加罗…...
大模型不再“一本正经地胡说八道”!揭秘RAG如何让AI「有据可查」
RAG(Retrieval-Augmented Generation)是一种结合信息检索与文本生成的AI架构,通过让大语言模型在回答问题前先查找外部知识库,有效缓解幻觉问题,并确保答案基于最新、专有数据。RAG通过文档切块、向量嵌入、向量检索和…...
沥青生产导向的常减压过程模拟及排产计划优化【附仿真】
✨ 长期致力于沥青生产、多目标优化、遗传算法、排产、换热网络综合、粒子群算法研究工作,擅长数据搜集与处理、建模仿真、程序编写、仿真设计。 ✅ 专业定制毕设、代码 ✅ 如需沟通交流,点击《获取方式》 (1)原油实沸点切割与沥青…...
