设计模式之适配器模式(Adapter)
一、适配器模式介绍
适配器模式(adapter pattern )的原始定义是:将类的接口转换为客户期望的另一个接口,
适配器可以让不兼容的两个类一起协同工作。
适配器模式是用来做适配,它将不兼容的接口转换为可兼容的接口,让原本由于接口
不兼容而不能一起工作的类可以一起工作。适配器模式有两种实现方式:类适配器和
对象适配器。其中,类适配器使用继承关系来实现,对象适配器使用组合关系来实现。
类适配器模式的耦合度比后者高,且要求程序员了解现有组件库中的相关组件的内部
结构,所以应用相对较少些。
二、适配器模式原理
适配器模式(Adapter)包含以下主要角色:
1)目标(Target)接口:当前系统业务所期待的接口,它可以是抽象类或接口。
2)适配者(Adaptee)类:适配者即被适配的角色,它是被访问和适配的现存组件库
中的组件接口。
3)适配器(Adapter)类:它是一个转换器,通过继承或引用适配者的对象,把适配
者接口转换成目标接口,让客户按目标接口的格式访问适配者。
类适配器类一般是继承 “适配者类(适配者的具体实现)” 并实现目标接口,而对象适配器
器类一般是在适配器类中引用适配者类对象;适配器模式结构图如下:
类适配器模式结构图:

对象适配器模式结构图:

三、适配器模式应用示例
以电脑目前只能读取SD卡的信息为例来看下适配器模式的使用
一台电脑目前只能读取SD卡的信息,这时我们想要使用电脑读取TF卡的内容, 就需要将TF卡
加上卡套,转换成SD卡,最后将TF卡中的内容读取出来
1、类适配器模式实现
实现方式:
类适配器类继承 “适配者类的具体实现(即TFCardImpl)” 并实现目标接口SDCard
UML类图如下:

具体代码实现如下:
/*** 类适配器* 以电脑目前只能读取SD卡的信息为例来看下适配器模式的使用* 一台电脑目前只能读取SD卡的信息,这时我们想要使用电脑读取TF卡的内容, 就需要将TF卡加上卡套,转换成SD卡** SD卡接口--目标(Target)接口*/
public interface SDCard {//读取SD卡方法String readSD();//写入SD卡功能void writeSD(String msg);
}/******************************************************** SD卡实现类*********************************************************/
public class SDCardImpl implements SDCard{@Overridepublic String readSD() {String msg = "sd card reading data";return msg;}@Overridepublic void writeSD(String msg) {System.out.println("sd card write data : " + msg);}
}/*** TF卡接口--适配者*/
public interface TFCard {//读取TF卡方法String readTF();//写入TF卡功能void writeTF(String msg);
}/******************************************************** TF卡实现类** *******************************************************/
public class TFCardImpl implements TFCard{@Overridepublic String readTF() {String msg = "tf card reading data";return msg;}@Overridepublic void writeTF(String msg) {System.out.println("tf card write data : " + msg);}
}/******************************************************** 定义适配器类,让SD卡兼容TF卡* 类适配器--通过继承来实现适配********************************************************/
public class SDAdapterTF extends TFCardImpl implements SDCard{@Overridepublic String readSD() {System.out.println("adapter read tf card ");return readTF();}@Overridepublic void writeSD(String msg) {System.out.println("adapter write tf card");writeTF(msg);}
}******************************************************** 电脑类,* 电脑类只能读取sd卡********************************************************/
public class Computer {public String read(SDCard sdCard){return sdCard.readSD();}
}//测试
public class Test {public static void main(String[] args) {Computer computer = new Computer();SDCard sdCard = new SDCardImpl();System.out.println(computer.read(sdCard));System.out.println("========================");SDAdapterTF adapterTF = new SDAdapterTF();System.out.println(computer.read(adapterTF));}
}
2、对象适配器模式实现
实现方式:
对象适配器模式可釆用将现有组件库中已经实现的组件引入适配器类中,该类同时实
现当前系统的业务接口。
对象适配器模式UML类图如下:

代码实现:
在类适配器模式的代码基础上我们只需要修改 “适配器类” 就可以了,具体代码如下:
/******************************************************** 适配器类* 对象适配器类--通过组合的方式来实现适配********************************************************/
public class SDAdapterTF2 implements SDCard {private TFCard tfCard;public SDAdapterTF2(TFCard tfCard){this.tfCard = tfCard;}@Overridepublic String readSD() {System.out.println("adapter read tf card ");return tfCard.readTF();}@Overridepublic void writeSD(String msg) {System.out.println("adapter write tf card");tfCard.writeTF(msg);}
}
四、适配器模式总结
1、适配器模式优点
1)将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,无序修改原有结构
2)增加了类的透明性和复用性,将具体业务实现过程封装在适配者类中,对于客户端类而言
是透明的,而且提高了适配者的复用性,同一个适配者类可以在多个不同的系统中复用。
3)灵活性和扩展性都非常好,通过使用配置文件可以很方便的更换适配器,也可以在不修改
原有代码的基础上增加新的适配器类,符合开闭原则。
2、适配器模式缺点
2.1、类适配器的缺点
1)对于Java等不支持多重继承的语言,一次最多只能适配一个适配者类,不能同时适配
多个适配者
2)适配者类不能为最终类,即不能被关键字final修饰
2.2、对象适配器的缺点
1)与类适配器模式相比较,在该模式下要在适配器中置换适配者类的某些方法比较麻烦。
3、适配器模式适用场景
1)统一多个类的接口设计时:
某个功能的实现依赖多个外部系统(或者说类)。通过适配器模式,将它们的接口适配为
统一的接口定义
2)需要依赖外部系统时:
当我们把项目中依赖的一个外部系统替换为另一个外部系统的时候,利用适配器模式,可
以减少对代码的改动
3)原有接口无法修改时或者原有接口功能太老旧但又需要兼容时:
如JDK1.0 Enumeration 到 Iterator 的替换,适用适配器模式保留 Enumeration 类,并将
其实现替换为直接调用 Itertor
4)适配不同数据格式时:
如Slf4j 日志框架,定义打印日志的统一接口,提供针对不同日志框架的适配器
4、代理、桥接、装饰与适配4种设计模式的区别
代理、桥接、装饰器、适配器,这 4 种模式是比较常用的结构型设计模式。它们的代码结构
非常相似。但其各自的用意却不同,简单说一下它们之间的关系:
1)代理模式:
代理模式在不改变原始类接口的条件下,为原始类定义一个代理类,主要目的是控制访问,
而非加强功能,这是它跟装饰器模式最大的不同。
2)桥接模式:
桥接模式的目的是将接口部分和实现部分分离,从而让它们可以较为容易、也相对独立地
加以改变。
3)装饰器模式:
装饰者模式在不改变原始类接口的情况下,对原始类功能进行增强,并且支持多个装饰器的
嵌套使用。
4)适配器模式:
将一个类的接口转换为客户希望的另一个接口。适配器模式让那些不兼容的类可以一起工作
相关文章:
设计模式之适配器模式(Adapter)
一、适配器模式介绍 适配器模式(adapter pattern )的原始定义是:将类的接口转换为客户期望的另一个接口, 适配器可以让不兼容的两个类一起协同工作。 适配器模式是用来做适配,它将不兼容的接口转换为可兼容的接口,让原本由于接口…...
[git] github管理项目之环境依赖管理
导出依赖到 requirements.txt pip install pipreqs pipreqs . --encodingutf8 --force但是直接使用pip安装不了torch,需要添加源!! pip install -r requirements.txt -f https://download.pytorch.org/whl/torch_stable.html想到一个麻烦的…...
【STM32 Blue Pill编程实例】-SD卡文件读写(SPI接口)
SD卡文件读写(SPI接口) 文章目录 SD卡文件读写(SPI接口)1、SD卡模块介绍2、硬件准备与接线3、模块配置3.1 SPI接口配置3.2 SPI接口的片选信号引脚配置3.3 FATFS配置4、代码实现在本文中,我们将介绍如何将 microSD 卡与 STM32 Blue Pill 连接,并在STM32CubeIDE中对SD卡进行…...
为什么需要软件测试?
软件测试 软件测试是评估和验证计算机程序或系统是否按预期运行的过程。 它涉及执行程序或系统以识别预期结果和实际结果之间的任何错误或差距。 目标是确保软件满足指定的要求,没有缺陷,并在不同场景中可靠地工作。 为什么需要软件测试?…...
成为超人:普通人如何白手起家,富一代和富二代的根本区别是什么?
成为超人:普通人如何白手起家,富一代和富二代的根本区别是什么? 我的问题是事业就讲 10 年装逼学习法失效① 光说不练,还是太懒真正的勤奋,解决温饱后,只专注赚钱这件事 ② 信念飘摇,随波流转万…...
Java 集合 Collection常考面试题
理解集合体系图 collection中 list 是有序的,set 是无序的 什么是迭代器 主要遍历 Collection 集合中的元素,所有实现了 Collection 的集合类都有一个iterator()方法,可以返回一个 iterator 的迭代器。 ArrayList 和 Vector 的区别? ArrayList 可以存放 null,底层是由数…...
C++继承与菱形继承(一文了解全部继承相关基础知识和面试点!)
目的减少重复代码冗余 Class 子类(派生类) : 继承方式 父类(基类) 继承方式共有三种:公共、保护、私有 父类的私有成员private无论哪种继承方式都不可以被子类使用 保护protected权限的内容在类内是可以访问,但是在…...
谷歌DeepMind 德米斯·哈萨比斯 因蛋白质预测AI荣获诺贝尔化学奖
2024年诺贝尔化学奖的一半授予了谷歌DeepMind的联合创始人兼首席执行官德米斯哈萨比斯和公司总监约翰M朱姆珀,以表彰他们在利用人工智能预测蛋白质结构方面的研究成果。另一半奖项则授予华盛顿大学生物化学教授大卫贝克,以表彰他在计算蛋白质设计领域的贡…...
内网笔记大全
内网笔记大全 1、基础命令 Windows 1、net user #查看用户 2、net view #查看在线主机 3、systeminfo #查看操作系统的基本配置 4、ipconfig /all #详细显示当前网络配置信息和网卡信息 5、net localgroup #查看本地组信息 6、net localgroup administrators #查看管理员组 7、…...
peft.LoraConfig()参数说明
LoraConfig()介绍 LoraConfig()是peft库中的一个配置类,用于设置大模型微调方法LoRA(Low-Rank Adaptation)的相关参数。PEFT 库为各种参数高效的微调方法(如 LoRA)提供了封装,以减少微调大模型时的计算资源…...
串口(UART)的FPGA设计(接收与发送模块)
目录 串口基础知识 一、什么是串口?有哪些特点? 二、常见的串口通信协议有哪些?他们有什么区别?...
JSON 格式化工具:快速便捷地格式化和查看 JSON 数据
JSON 格式化工具:快速便捷地格式化和查看 JSON 数据 为什么需要 JSON 格式化工具? 在日常开发和调试中,JSON 是非常常见的数据交换格式。无论是前端与后端的接口调用,还是数据存储和处理,JSON 格式都扮演着重要角色。…...
【星汇极客】STM32 HAL库各种模块开发之1.8TFT屏幕
前言 本人是一名嵌入式学习者,在大学期间也参加了不少的竞赛并获奖,包括:江苏省电子设计竞赛省一、睿抗机器人国二、中国高校智能机器人国二、嵌入式设计竞赛国三、光电设计竞赛国三、节能减排竞赛国三等。 暑假的时候参加了太多的比赛&#…...
Excel中使用SQL语句的四种方法
总结在 Excel 中使用 SQL 语句的四种方法,各种方法都有各自的适用场景,可以选择自己熟悉的或喜欢方式。本文以在 Excel 中操作 MS SQL 数据库的数据为例进行说明。MS SQL 的数据如下,使用微软 SQLExpress 版本。 方法 1: Excel 现…...
目标检测中的损失函数
损失函数是用来衡量模型与数据的匹配程度的,也是模型权重更新的基础。计算损失产生模型权重的梯度,随后通过反向传播算法,模型权重得以更新进而更好地适应数据。一般情况下,目标损失函数包含两部分损失,一个是目标框分…...
list库实现
list库实现的要点: 构建list类时,需要同时构建struct Node来存储节点信息,list类中只存储哨兵位节点信息,迭代器类需要template<T,Ptr,Ref>来构建const和非const迭代器,迭代器中也是存储节点信息。反向迭代器也…...
MFC工控项目实例二十三模拟量输入设置界面
承接专栏《MFC工控项目实例二十二主界面计数背景颜色改变》 1、在SenSet.h文件中添加代码 #include "BtnST.h" #include "ShadeButtonST.h"/ // SenSet dialogclass SenSet : public CDialog { // Construction public:SenSet(CWnd* pParent NULL); //…...
排序算法总结(三)希尔排序
访问www.tomcoding.com网站,学习Oracle内部数据结构,详细文档说明,下载Oracle的exp/imp,DUL,logminer,ASM工具的源代码,学习高技术含量的内容。 如果你在网上搜一下希尔排序,都会告…...
如何迁移 Linux 服务器 第一部分 - 系统准备
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 简介 在许多情况下,您可能需要将数据和操作需求从一个服务器迁移到另一个服务器。您可能需要在新的数据中心实施解决方案&a…...
网络IO模型都有哪些
“网络IO模型有BIO、NIO、AIO ” “他们分别代表什么,有什么区别吗? BIO:同步阻塞IO。 NIO:同步非阻塞IO。 AIO:异步非阻塞IO。 “BIO为什么是同步阻塞IO,他阻塞的是谁跟谁之间的关联?”。 首先…...
测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...
循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
Linux-07 ubuntu 的 chrome 启动不了
文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...
拉力测试cuda pytorch 把 4070显卡拉满
import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试,通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小,增大可提高计算复杂度duration: 测试持续时间(秒&…...
企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
c++第七天 继承与派生2
这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分:派生类构造函数与析构函数 当创建一个派生类对象时,基类成员是如何初始化的? 1.当派生类对象创建的时候,基类成员的初始化顺序 …...
