当前位置: 首页 > news >正文

GPT带我学-设计模式-适配器模式

1 什么是适配器设计模式

适配器设计模式是一种结构性设计模式,用于在不兼容的接口之间进行转换。它允许将一个类的接口转换成客户端所期望的接口。

适配器模式包含以下几个角色:

目标接口(Target):定义客户端所期望的接口。
适配器(Adapter):实现目标接口,同时持有被适配者的实例,将客户端的请求转发给被适配者。
被适配者(Adaptee):已存在的类或接口,不符合客户端的需求。
客户端(Client):通过适配器来调用被适配者的功能。

适配器模式可以解决以下问题:

在系统中使用已存在的类,但其接口与系统要求的接口不一致。
在客户端需要使用不可直接访问的类时,可以通过适配器来间接访问。

适配器模式的优点包括:

可以重新使用已存在的类,不需要修改其源代码。
提供了灵活性,可以在系统中引入新的类。

然而,适配器模式也存在一些缺点:

引入了一个额外的结构,增加了系统的复杂度。
可能会导致系统的性能下降。

总体而言,适配器设计模式是一种实现接口转换的方法,可以在不改变现有代码的情况下使不兼容的接口能够协同工作。

2 适配器模式有几种形式?

适配器模式有两种形式:

类适配器模式:这种形式下,适配器类继承自已存在的类,并同时实现目标接口。适配器类通过继承已存在的类,使得目标接口与被适配者接口能够兼容。类适配器模式使用多重继承实现,因此只适用于支持多重继承的编程语言。

对象适配器模式:这种形式下,适配器类持有被适配者的实例,并实现目标接口。适配器类通过调用被适配者的方法来完成客户端的请求。对象适配器模式使用组合(对象持有)实现,因此可以适用于任何支持对象组合的编程语言。

无论是类适配器模式还是对象适配器模式,其目的都是为了将被适配者的接口转换成目标接口。选择哪种形式取决于所用编程语言的特性以及具体的应用场景。

3 请用java举一个实际的例子帮助我理解适配器模式

假设我们有一个音乐播放器程序,它能够播放MP3格式的音乐文件。现在我们引入了一个新的音乐库,它提供了一些高质量的WAV格式音乐文件,但是我们的音乐播放器只能播放MP3格式的文件。这时,我们可以使用适配器模式来解决兼容性问题。

首先,我们需要定义目标接口,即音乐播放器所期望的接口:

public interface MediaPlayer {void play(String fileName);
}

然后,我们实现一个MP3播放器类,负责播放MP3格式的音乐文件:

public class Mp3Player implements MediaPlayer {@Overridepublic void play(String fileName) {System.out.println("Playing MP3 file: " + fileName);}
}

接下来,我们需要适配器类来将WAV文件适配为MP3格式。适配器类会实现目标接口,并持有被适配者的实例:

public class WavToMp3Adapter implements MediaPlayer {private WavPlayer wavPlayer;public WavToMp3Adapter(WavPlayer wavPlayer) {this.wavPlayer = wavPlayer;}@Overridepublic void play(String fileName) {wavPlayer.playWav(fileName);}
}

被适配者类WavPlayer负责播放WAV格式的音乐文件:

public class WavPlayer {public void playWav(String fileName) {System.out.println("Playing WAV file: " + fileName);}
}

最后,我们可以在客户端代码中使用适配器模式来播放不同格式的音乐文件:

public class Client {public static void main(String[] args) {MediaPlayer mp3Player = new Mp3Player();MediaPlayer wavPlayer = new WavToMp3Adapter(new WavPlayer());mp3Player.play("song.mp3");  // 播放MP3文件wavPlayer.play("song.wav");  // 使用适配器,播放WAV文件}
}

执行结果

Playing MP3 file: song.mp3
Playing WAV file: song.wav

客户端代码中,我们可以看到通过适配器类,我们成功地播放了WAV格式的音乐文件。适配器模式帮助我们将不兼容的WAV文件适配为MP3文件,使得我们的音乐播放器能够正常播放不同格式的音乐文件。

4 适配器模式主要应用在哪些场景

适配器模式主要应用于以下场景:

将旧接口适配成新接口:当需要使用一个已经存在的类,但是它的接口与你的需求不兼容时,可以使用适配器模式。适配器将旧接口转换为目标接口,使得客户端可以通过目标接口调用旧接口的功能。

多个类的接口统一:当多个类具有不同的接口,但需要以统一的方式使用它们时,可以使用适配器模式。适配器模式可以将这些类的接口适配成一个统一的接口,使得客户端可以一致地调用它们。

封装外部依赖:当需要与外部的组件或库进行交互,并且想要将其隐藏在自己的代码中时,可以使用适配器模式。适配器模式可以封装对外部依赖的调用,使得客户端无需直接与外部依赖进行交互。

兼容新旧版本:当需要兼容不同版本的组件或库时,可以使用适配器模式。适配器可以根据不同的版本提供不同的实现,使得客户端能够适应不同的版本。

总的来说,适配器模式的主要目的是解决接口不兼容的问题,使得不兼容的类能够协同工作。适配器模式可以帮助降低代码的耦合度,提高代码的复用性和可扩展性。

5 spring源码中在哪里使用了适配器模式?

在Spring源码中,有几个地方使用了适配器模式。

HandlerAdapter:Spring MVC框架中的HandlerAdapter接口及其实现类就是适配器模式的应用。它负责将请求分发给对应的Controller处理,并将结果返回给前端。Spring提供了多种HandlerAdapter的实现类,适配不同类型的Controller处理方式,如注解控制器、类层次结构控制器、同步和异步控制器等。

MessageListenerAdapter:Spring的消息驱动模块中,MessageListenerAdapter就是一个适配器模式的实例。它将底层的消息监听器(如javax.jms.MessageListener)适配成一个特定的Spring MessageListener,使得底层监听器能够在Spring消息驱动容器中被使用。

DefaultAdvisorAdapterRegistry:Spring AOP模块中的AdvisorAdapter就是适配器模式的应用。Spring AOP中使用Advisor和Advice来实现方法拦截和增强,而AdvisorAdapter负责将不同类型的Advice适配成统一的Advisor接口实现类,以便统一管理。

这些都是Spring源码中使用适配器模式的一些例子,它们都用于将不同的接口适配成统一的接口,以便进行统一处理或使用。适配器模式在Spring中的应用帮助实现了框架的灵活性和扩展性。

相关文章:

GPT带我学-设计模式-适配器模式

1 什么是适配器设计模式 适配器设计模式是一种结构性设计模式,用于在不兼容的接口之间进行转换。它允许将一个类的接口转换成客户端所期望的接口。 适配器模式包含以下几个角色: 目标接口(Target):定义客户端所期望…...

Pyecharts教程(七):使用pyecharts创建堆叠柱状图的示例

Pyecharts教程(七):使用pyecharts创建堆叠柱状图的示例 作者:安静到无声 个人主页 目录 Pyecharts教程(七):使用pyecharts创建堆叠柱状图的示例完整代码推荐专栏在数据可视化中,柱状图是一种常见的图表类型,它可以清晰地展示各类别之间的比较关系。然而,如果我们想要在同…...

C++中的强制转换的常用类型及应用场景详解

C中的强制转换的常用类型及应用场景详解 文章目录 C中的强制转换的常用类型及应用场景详解一、静态转换(static_cast)二、动态转换(dynamic_cast)三、常量转换(const_cast)四、重新解释转换(rei…...

ubuntu调整时区

ubuntu在新装系统的时候,所用的时区不一定是8的时区,需要设置一下,否则执行cron等定时任务的时候,时间就会不对 查看当前系统的时区 date -R tzselect 选择时区,但是没用 ,作用可能就是 选择时区 设置时区:…...

mybatis:动态sql【2】+转义符+缓存

目录 一、动态sql 1.set、if 2.foreach 二、转义符 三、缓存cache 1. 一级缓存 2. 二级缓存 一、动态sql 1.set、if 在update语句中使用set标签&#xff0c;动态更新set后的sql语句&#xff0c;&#xff0c;if作为判断条件。 <update id"updateStuent" pa…...

2021年09月 C/C++(五级)真题解析#中国电子学会#全国青少年软件编程等级考试

第1题:抓牛 农夫知道一头牛的位置,想要抓住它。农夫和牛都位于数轴上,农夫起始位于点N(0<=N<=100000),牛位于点K(0<=K<=100000)。农夫有两种移动方式: 1、从X移动到X-1或X+1,每次移动花费一分钟 2、从X移动到2*X,每次移动花费一分钟 假设牛没有意识到农夫的…...

Ansible学习笔记1

公司的服务器越来越多&#xff0c;维护一些简单的事情都会变得很繁琐。用Shell脚本来管理少量服务器效率还行&#xff0c;服务器多了&#xff0c;Shell脚本无法实现高效率运维。这种情况下&#xff0c;我们需要引入自动化运维工具&#xff0c;对多台服务器实现高效运维。 配置服…...

解决centos离线安装cmake找不到OpenSSL问题

安装方法&#xff1a;见另外一篇文章 https://blog.csdn.net/zhongxj183/article/details/118488629 按照文章下载了离线gcc 和OpenSSL&#xff0c;以及在cmake官网下载了最新版 cmake-3.27.4.tar.gz 顺利安装gcc 和OpenSSL 但执行编译cmake时&#xff0c;报错找不到OpenSSL…...

Java 中数据结构ArrayList的用法

Java ArrayList ArrayList 类是一个可以动态修改的数组&#xff0c;与普通数组的区别就是它是没有固定大小的限制&#xff0c;我们可以添加或删除元素。 方法集合样例代码 import java.util.*;public class list_set_iterator {public static void main(String[] args) {Lis…...

UDP 多播(组播)

前言&#xff08;了解分类的IP地址&#xff09; 1.组播&#xff08;多播&#xff09; 单播地址标识单个IP接口&#xff0c;广播地址标识某个子网的所有IP接口&#xff0c;多播地址标识一组IP接口。单播和广播是寻址方案的两个极端&#xff08;要么单个要么全部&#xff09;&am…...

分布式环境集成JWT(Java Web Token)

目录 一&#xff0c;说明&#xff1a;二&#xff0c;Token、Session和Cookie比较三&#xff0c;Spring Boot项目集成JWT1&#xff0c;引入依赖2&#xff0c;Token工具类3&#xff0c;定义拦截器4&#xff0c;注册拦截器5&#xff0c;编写登录代码6&#xff0c;测试 四&#xff…...

Python实战之数据表提取和下载自动化

在网络爬虫领域&#xff0c;动态渲染类型页面的数据提取和下载自动化是一个常见的挑战。本文将介绍如何利用Pyppeteer库完成这一任务&#xff0c;帮助您轻松地提取动态渲染页面中的数据表并实现下载自动化。 一、环境准备 首先&#xff0c;确保您已经安装了Python环境。接下来…...

Midjourney学习(三)6个高级应用

使用Remix Mode在原图片的基础上进行二次创作 通过prompt得到大图之后&#xff0c;点击Make Variations按钮&#xff0c;输入Remix Prompt&#xff0c;即可得到意想不到的效果&#xff01; 局部内容重绘 通过局部重绘可以实现对画面内容更加精细化的控制&#xff0c;同样也是需…...

C语言:指针类型的意义

1.指针的类型决定了解引用时访问几个字节 2.指针的类型决定了指针1、-1跳过几个字节 一、指针的类型决定指针解引用时访问几个字节 例如 int 型指针解引用时访问4个字节 char 型指针解引用时访问1个字节 详解代码如下&#xff1a; int b 0x11223344&#xff08;十六进制&…...

如何将 PDF 转换为 Word:前 5 个应用程序

必须将 PDF 转换为 Word 才能对其进行编辑和自定义。所以这里有 5 种很棒的方法 PDF 文件被广泛使用&#xff0c;因为它非常稳定且难以更改。这在处理法律合同、财务文件和推荐信等重要文件时尤其重要。但是&#xff0c;有时您可能需要编辑 PDF 文件。最好的方法是使用应用程序…...

AP5192 DC-DC降压恒流LED汽车头灯摩托车电动车大灯电源驱动

AP5192是一款PWM工作模式,高效率、外围简单、 内置功率MOS管&#xff0c;适用于4.5-100V输入的高精度 降压LED恒流驱动芯片。最大电流1.5A。 AP5192可实现线性调光和PWM调光&#xff0c;线性调光 脚有效电压范围0.55-2.6V. AP5192 工作频率可以通过RT 外部电阻编程 来设定&…...

Python Opencv实践 - Canny边缘检测

import cv2 as cv import numpy as np import matplotlib.pyplot as pltimg cv.imread("../SampleImages/pomeranian.png", cv.IMREAD_GRAYSCALE) print(img.shape)#图像Canny边缘检测 #cv.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradien…...

Python编程练习与解答 练习119:低于和高于平均水平

编写一个程序&#xff0c;从用户处读取数字&#xff0c;直到用户输入空行。程序应该显示用户输入的所有值的平均值。然后所有程序应该显示所有平均值的值&#xff0c;然后显示所有平均值&#xff08;若有&#xff09;&#xff0c;最后显示所有高于平均值的值。再每个值列表之前…...

vue中的nextTick的作用

vue里面&#xff0c;常用的事件onMounted里&#xff0c;总喜欢用一个nextTick&#xff1a; onMounted(() > {nextTick(() > {init();}); });这个东西有啥用呢&#xff1f;我总搞不懂。 今天我忽然有点明白了。这是一个跟前面语句有关的方法。意思是&#xff0c;等前面的…...

如何通过四个步骤清理网络防火墙规则

组织必须确保适当的安全策略到位&#xff0c;以保护其投资并优化其安全有效性。然而&#xff0c;随着网络的扩展和复杂性的增加&#xff0c;网络运营团队面临着管理来自多个供应商的大量防火墙和网络设备的挑战。他们必须解决分散的基础设施、职能孤岛、人员配置问题、分散的管…...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

自然语言处理——Transformer

自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效&#xff0c;它能挖掘数据中的时序信息以及语义信息&#xff0c;但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN&#xff0c;但是…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比

目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec&#xff1f; IPsec VPN 5.1 IPsec传输模式&#xff08;Transport Mode&#xff09; 5.2 IPsec隧道模式&#xff08;Tunne…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。

1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj&#xff0c;再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

回溯算法学习

一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行

项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战&#xff0c;克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...

LRU 缓存机制详解与实现(Java版) + 力扣解决

&#x1f4cc; LRU 缓存机制详解与实现&#xff08;Java版&#xff09; 一、&#x1f4d6; 问题背景 在日常开发中&#xff0c;我们经常会使用 缓存&#xff08;Cache&#xff09; 来提升性能。但由于内存有限&#xff0c;缓存不可能无限增长&#xff0c;于是需要策略决定&am…...

Git常用命令完全指南:从入门到精通

Git常用命令完全指南&#xff1a;从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...