设计模式 - 结构型模式考点篇:适配器模式(类适配器、对象适配器、接口适配器)
目录
一、适配器模式
一句话概括结构式模式
1.1、适配器模式概述
1.2、案例
1.2.1、类适配器模式实现案例
1.2.2、对象适配器
1.2.3、接口适配器
1.3、优缺点(对象适配器模式)
1.4、应用场景
一、适配器模式
一句话概括结构式模式
教你将类和对象结合再一起形成一个更强大的结构.
1.1、适配器模式概述
将一个类的接口转换成客户希望的另一个接口,使得原本不兼容的接口能一起工作.
比如,如果你使用的是苹果手机,那么就意味着充电器的充电口也是苹果标准的,而你现在只有一个 type-c 插孔的插座能充电,因此就需要一个转换器(一头type-c,另一头 苹果插头),就可以让原本不兼容的 苹果插头 一起工作.
适配器模式包含以下主机角色:
- 目标接口:当前客户所期待的接口,它可以是抽象类或者接口(上述的 苹果插头).
- 适配者类:是被访问的现存组件库中的接口(上述的 type-c).
- 适配器类:是一个转换器,通过继承或引用目标接口,实现适配者类的所有方法,就可以实现转换效果.
适配器模式分为 类适配器模式、对象适配器模式 ,其中类适配器耦合度最高(不符合合成/聚合复用原则),且要求程序员了解现有组件库的内部结构,因此应用较少.
还有一种模式叫 接口适配器模式,是对对象适配器的扩展.
1.2、案例
现有一台电脑,只能读取 SD 卡,而我现在只有一个 TF 卡,因此就需要使用适配器模式. 创建一个读卡器,将 TF 卡中的内容读取出来.
1.2.1、类适配器模式实现案例
类适配器只需要我们继承目标接口,实现适配者接口的所有方法即可.
/*** 目标接口: TF 卡*/
public interface TFCard {/*** 读取 TF 卡* @return*/String readTF();/*** 写入 TF 卡*/void writeTF(String msg);}
/*** 目标接口实现类*/
public class TFCardImpl implements TFCard{@Overridepublic String readTF() {String msg = "tf card readTF: hello!";return msg;}@Overridepublic void writeTF(String msg) {System.out.println("tf card writeTF: hello!");}}
/*** 适配者接口: SD 卡*/
public interface SDCard {/*** 读取 SD 卡* @return*/String readSD();/*** 写入 SD 卡*/void writeSD(String msg);}
/*** 适配者实现类: SD 卡实现类*/
public class SDCardImpl implements SDCard {@Overridepublic String readSD() {String msg = "sd card readTF: hello!";return msg;}@Overridepublic void writeSD(String msg) {System.out.println("sd card writeTF: " + 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);}}
/*** 电脑类*/
public class Computer {public String readSD(SDCard sdCard) {if(sdCard == null) {throw new NullPointerException("sd card null");}return sdCard.readSD();}}
public static void main(String[] args) {//1.创建一个电脑类Computer computer = new Computer();//3.通过适配器从电脑中读取 TF 卡的数据SDAdapterTF adapter = new SDAdapterTF();String msg = computer.readSD(adapter);System.out.println(msg);}
1.2.2、对象适配器
对象适配器,相比于 类适配器,更符合 合成/聚合复用原则(持有新对象的引用,而不是通过继承来达到复用目的). 也就是说,它是通过持有目标接口的引用(tf 卡接口的引用),重写 适配者接口 的所有方法实现的 .
/*** 目标接口: TF 卡*/
public interface TFCard {/*** 读取 TF 卡* @return*/String readTF();/*** 写入 TF 卡*/void writeTF(String msg);}
/*** 目标接口实现类*/
public class TFCardImpl implements TFCard {@Overridepublic String readTF() {String msg = "tf card readTF: hello!";return msg;}@Overridepublic void writeTF(String msg) {System.out.println("tf card writeTF: hello!");}}
/*** 适配者接口: SD 卡*/
public interface SDCard {/*** 读取 SD 卡* @return*/String readSD();/*** 写入 SD 卡*/void writeSD(String msg);}
/*** 适配者实现类: SD 卡实现类*/
public class SDCardImpl implements SDCard {@Overridepublic String readSD() {String msg = "sd card readTF: hello!";return msg;}@Overridepublic void writeSD(String msg) {System.out.println("sd card writeTF: " + msg);}}
/*** 适配器:SD 兼容 TF*/
public class SDAdapterTF implements SDCard {private TFCard tfCard;public SDAdapterTF(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);}}
/*** 电脑类*/
public class Computer {public String readSD(SDCard sdCard) {if(sdCard == null) {throw new NullPointerException("sd card null");}return sdCard.readSD();}}
public class Client {public static void main(String[] args) {//1.创建一个电脑类Computer computer = new Computer();//3.通过适配器从电脑中读取 TF 卡的数据SDAdapterTF adapter = new SDAdapterTF(new TFCardImpl());computer.readSD(adapter);}}
1.2.3、接口适配器
当我们不希望实现一个适配者接口(sd 卡接口)中的所有方法时,可以创建一个抽象类 Adapter,实现所有方法(不用实现方法内容).此时我们只需要继承该抽象类,在重写我们需要的方法即可.
实现前两个适配器中,就一直没有使用 writeSD 方法,因此这里就不实现此方法.
/*** 目标接口: TF 卡*/
public interface TFCard {/*** 读取 TF 卡* @return*/String readTF();/*** 写入 TF 卡*/void writeTF(String msg);}
/*** 目标接口实现类*/
public class TFCardImpl implements TFCard {@Overridepublic String readTF() {String msg = "tf card readTF: hello!";return msg;}@Overridepublic void writeTF(String msg) {System.out.println("tf card writeTF: hello!");}}
/*** 适配者接口: SD 卡*/
public interface SDCard {/*** 读取 SD 卡* @return*/String readSD();/*** 写入 SD 卡*/void writeSD(String msg);}
/*** 适配者实现类: SD 卡实现类*/
public class SDCardImpl implements SDCard {@Overridepublic String readSD() {String msg = "sd card readTF: hello!";return msg;}@Overridepublic void writeSD(String msg) {System.out.println("sd card writeTF: " + msg);}}
public abstract class Adapter implements SDCard {@Overridepublic void writeSD(String msg) {}@Overridepublic String readSD() {return null;}}
public class SDAdapterTF extends Adapter implements SDCard{private TFCard tfCard;public SDAdapterTF(TFCard tfCard) {this.tfCard = tfCard;}@Overridepublic String readSD() {System.out.println("adapter read tf card");return tfCard.readTF();}
}
/*** 电脑类*/
public class Computer {public String readSD(SDCard sdCard) {if(sdCard == null) {throw new NullPointerException("sd card null");}return sdCard.readSD();}}
public class Client {public static void main(String[] args) {//1.创建一个电脑类Computer computer = new Computer();//2.通过适配器从电脑中读取 TF 卡的数据SDAdapterTF sdAdapterTF = new SDAdapterTF(new TFCardImpl());String msg = computer.readSD(sdAdapterTF);System.out.println(msg);}}
1.3、优缺点(对象适配器模式)
优点
1. 适配现有类,且不修改类:在不改变现有类的基础上,实现现有类和目标类的接口的匹配.
2. 符合 合成/聚合 复用原则:持有引用,而不继承.
3. 符合开闭原则:如果引入新的目标接口,只需要在适配器类中进行扩展,不需要修改原代码.
缺点:
增加复杂性:编写适配器类时,要考虑全面,包括适配者和目标类.
1.4、应用场景
1. 以前开发的系统中存在满足当前业务所需要的类,但是接口和当前业务所需接口不一致.
2. 第三方提供的组件,但是组件接口定义和自己要求的接口定义不同.

相关文章:
设计模式 - 结构型模式考点篇:适配器模式(类适配器、对象适配器、接口适配器)
目录 一、适配器模式 一句话概括结构式模式 1.1、适配器模式概述 1.2、案例 1.2.1、类适配器模式实现案例 1.2.2、对象适配器 1.2.3、接口适配器 1.3、优缺点(对象适配器模式) 1.4、应用场景 一、适配器模式 一句话概括结构式模式 教你将类和对…...
android Google官网 :支持不同的语言和文化 rtl / ltr : 本地化适配:RTL(right-to-left) 适配
参考 google官网: 支持不同的语言和文化 应用包含可能专门针对特定文化而设计的资源。例如,应用可以包含针对特定文化的字符串,这些字符串将转换为当前语言区域的语言。 将具有文化特异性的资源与应用的其他资源分开是一种很好的做法。And…...
Visual Studio Code配置C/C++开发环境
C/C开发中的IDE非常多,网上有推荐安装Visual Studio 2019/2020/2022。但是登录官方网址下载,此软件体积非常大(8G以上),且企业版、专业版会收费。 因此,我们推荐大家可以尝试通过Visual Studio Code来配置C/C开发环境 环境准备 Mi…...
室内渲染的艺术:创造理想空间的视觉魔法!
在繁忙的生活中,我们常常渴望拥有一个属于自己的安静空间。这个空间可以是一间温馨的卧室,也可以是一间舒适的客厅,甚至可以是一个小小的书房。而这个空间的营造,离不开室内渲染。 室内渲染是一种艺术,它用色彩、光线…...
php发送get、post请求的6种方法简明总结?
这篇文章主要介绍php发送get、post请求的6种方法简明总结,分别为使用file_get_contents 、fopen、fsockopen、curl来发送GET和POST请求,需要的朋友可以参考下 方法1: 用file_get_contents 以get方式获取内容: <?php $urlhttp://www.51growup.com/; $html f…...
Go基础之变量和常量
Go基础之变量和常量 文章目录 Go基础之变量和常量一. 标识符、关键字、内置类型和函数1.1 标识符1.2 关键字1.3 保留字1.4 内置类型1.4.1 值类型:1.4.2 引用类型:(指针类型)1.5 内置函数1.6 内置接口error 二.Go变量命名规范2.1 采用驼峰体命名2.2 简单、…...
红队专题-Cobalt strike4.5二次开发
红队专题 招募六边形战士队员IDEA 自动换行原版CS反编译破解jar包反编译拔掉暗桩初始环境效果 stageless beacon http通信协议 过程分析上线&心跳get请求teamserver 处理请求 参考链接 招募六边形战士队员 一起学习 代码审计、安全开发、web攻防、逆向等。。。 私信联系 …...
Java数据结构之Deque(双端队列)
一、Queue和Deque异同介绍 我们知道,Queue是队列,只能一头进,另一头出。 如果把条件放松一下,允许两头都进,两头都出,这种队列叫双端队列(Double Ended Queue),学名Deq…...
flink以增量+全量的方式更新广播状态
背景 flink在实现本地内存和db同步配置表信息时,想要做到类似于增量(保证实时性) 全量(保证和DB数据一致)的效果,那么我们如何通过flink的广播状态外部定时器定时全量同步的方式来实现呢? 实现增量全量的效果 package wikiedits.schedule…...
Java:org.apache.commons.io包的工具类:IOUtils、FileUtils、FilenameUtils
文档 https://commons.apache.org/proper/commons-io/https://central.sonatype.com/artifact/commons-io/commons-io/2.14.0/jar 工具类 IOUtils io工具类FileUtils 文件操作工具类FilenameUtils 文件名工具类 依赖 <dependency><groupId>commons-io</gro…...
【JavaEE】文件操作
文章目录 前言什么是文件树型结构组织和目录文件路径文件类型文件权限Java中的文件操作File 类的常见属性File 类常见构造方法File 类常用方法 前言 文件是我们日常生活中使用非常广泛的,我们使用任何一个程序都离不开文件操作,这个文件不仅仅指平时可以…...
高精度电流源的应用领域有哪些
高精度电流源是一种能够提供稳定、准确、可控的电流输出的仪器设备,广泛应用于多个领域。以下是一些高精度电流源的应用领域。 科学研究:在物理学、化学、材料科学等领域中,需要进行精确的电流实验和测试。高精度电流源可以提供稳定的电流输出…...
多线程 - 线程池
线程池 相关的背景知识 线程池存在的意义: 使用进程来实现并发编程,效率太低了,任务太重了,为了提高效率,此时就引入了线程,线程也叫做“轻量级进程”,创建线程比创建进程更高效;销毁线程比销毁进程更高效;调度线程比调度进程更高效…此时,使用多线程就可以在很多时候代替进程…...
vue3 setup中defineEmits与defineProps的使用案例
目录 一、defineEmits的使用 二、 defineProps的使用 总结 一、defineEmits的使用 使用说明 1、在子组件中调用defineEmits并定义要发射给父组件的方法 const emits defineEmits([foldChange]) 2、使用defineEmits会返回一个方法,使用一个变量emits(变量名随意…...
Vs - Qt - 下拉窗口示例
下列代码定义了一个窗口,窗口采用竖直布局:一个按钮及一个label。按下按钮时候,窗口扩张,显示label控件。再次按下按钮时,窗口收缩,隐藏label控件。 详细代码如下: #include <QApplication&g…...
深圳自贸区的形成与发展
深圳自贸区的形成与发展源于中国政府推出的自贸试验区政策。自贸试验区是指在特定区域内,允许实行特殊的行政管理措施和贸易政策,以促进贸易自由化、投资便利化和经济转型升级。 深圳自贸区成立于2015年4月以来,主要着眼于优化区域布局、提高…...
机器人中的数值优化(二十一)—— 伴随灵敏度分析、线性方程组求解器的分类和特点、优化软件
本系列文章主要是我在学习《数值优化》过程中的一些笔记和相关思考,主要的学习资料是深蓝学院的课程《机器人中的数值优化》和高立编著的《数值最优化方法》等,本系列文章篇数较多,不定期更新,上半部分介绍无约束优化,…...
BACnet /IP转MQTT网关
在工业自动化和楼宇自动化领域中,Modbus、MQTT和BACnet/IP是三种常用的通信协议。Modbus是一种串行通信协议,常用于连接工业电子设备;MQTT是一种基于发布/订阅模式的轻量级通信协议,适用于远程监测和控制系统;BACnet/I…...
Web API 基础 (Web Workers API)
Web Workers API 1、指南 1.1 使用Web Workers Web Workers是一种让Web内容在后台线程中运行脚本的简单方法。工作线程可以在不干扰用户界面的情况下执行任务。此外,它们还可以使用XMLHttpRequest(尽管responseXML和channel属性总是为空)或fetch(没有此类限制)执…...
如何看待程序员不写注释?
程序员对代码注释可以说是又爱又恨又双标……你是怎么看待程序员不写注释这一事件的呢? 对于程序员来说,注释是一种非常重要的实践,可以帮助他们自己和其他人更好地理解和维护代码。以下是一些关于注释的观点: 维护代码的重要性&a…...
MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...
Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
智能AI电话机器人系统的识别能力现状与发展水平
一、引言 随着人工智能技术的飞速发展,AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术,在客户服务、营销推广、信息查询等领域发挥着越来越重要…...
Neko虚拟浏览器远程协作方案:Docker+内网穿透技术部署实践
前言:本文将向开发者介绍一款创新性协作工具——Neko虚拟浏览器。在数字化协作场景中,跨地域的团队常需面对实时共享屏幕、协同编辑文档等需求。通过本指南,你将掌握在Ubuntu系统中使用容器化技术部署该工具的具体方案,并结合内网…...
rm视觉学习1-自瞄部分
首先先感谢中南大学的开源,提供了很全面的思路,减少了很多基础性的开发研究 我看的阅读的是中南大学FYT战队开源视觉代码 链接:https://github.com/CSU-FYT-Vision/FYT2024_vision.git 1.框架: 代码框架结构:readme有…...
大模型真的像人一样“思考”和“理解”吗?
Yann LeCun 新研究的核心探讨:大语言模型(LLM)的“理解”和“思考”方式与人类认知的根本差异。 核心问题:大模型真的像人一样“思考”和“理解”吗? 人类的思考方式: 你的大脑是个超级整理师。面对海量信…...
【Java】Ajax 技术详解
文章目录 1. Filter 过滤器1.1 Filter 概述1.2 Filter 快速入门开发步骤:1.3 Filter 执行流程1.4 Filter 拦截路径配置1.5 过滤器链2. Listener 监听器2.1 Listener 概述2.2 ServletContextListener3. Ajax 技术3.1 Ajax 概述3.2 Ajax 快速入门服务端实现:客户端实现:4. Axi…...
