java设计模式学习之【适配器模式】

文章目录

  • 引言
  • 适配器模式简介
    • 定义与用途:
    • 实现方式:
      • 类型
  • 使用场景
  • 优势与劣势
  • 适配器模式在Spring中的应用
  • 多媒体播放器示例
  • 代码地址

引言

在我们的日常生活中,适配器无处不在:无论是将不同国家的插头转换成本地标准,还是连接新型耳机和传统音频端口,适配器在我们生活中扮演着重要角色。同样,在软件开发领域,适配器模式也扮演着类似的角色,帮助不兼容的接口实现协同工作。想象一下,如果你有两个组件,它们功能强大,但因为接口不匹配而无法一起工作,该怎么办?适配器模式在这里就像是一个多功能转换插头,连接这些组件,让它们可以协同工作。

适配器模式简介

适配器模式是一种结构型设计模式,它允许你将一个类的接口转换成客户端期望的另一种接口。适配器模式使得原本由于接口不兼容而不能一起工作的类可以协同工作。

定义与用途:

  1. 适配器模式主要用于解决两个已有接口之间不匹配的问题,无需修改现有的代码。
  2. 它常用于系统升级或整合过程中,特别是在需要整合第三方库或遗留系统时。

实现方式:

通过将类的实例化过程从客户端代码转移到工厂类,从而减少客户端的复杂性。
适配器模式通常通过创建一个包装类,这个包装类持有一个对已有类的引用,并实现了目标接口。

类型

适配器模式主要有两种类型:

  • 类适配器(Class Adapter):通过继承来实现适配。
  • 对象适配器(Object Adapter):通过组合来实现适配。

使用场景

适配器模式在以下情况下非常有用:

  • 当你想使用一些现有的类,但其接口不符合你的需求。
  • 当你想创建一个可重用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作。
  • 当你需要使用几个现有的子类,但是不可能对每一个都进行子类化以匹配它们的接口。适配器可以调整其父接口。

优势与劣势

  • 优势
  • 增加了类的透明性:隐藏了具体实现,客户端代码可以通过统一的接口与不同的实现进行交互。
  • 提高了类的复用性:原本由于接口不兼容无法一起工作的类可以在适配器的帮助下协同工作。
  • 灵活性和扩展性:可以在不修改原有代码的情况下引入新的适配器,使得系统更加灵活。
  • 劣势
  • 过多的使用会使系统变得杂乱:每个适配器都会增加系统的复杂性。
  • 可能会导致代码理解和维护的困难:特别是当有很多适配器参与时,理解它们之间的关系可能会很困难。
  • 增加系统的代码量:为了适配不同的接口,可能需要编写额外的适配器代码。

适配器模式在Spring中的应用

Spring框架中广泛应用了适配器模式,尤其在Spring MVC框架中。Spring用适配器模式来兼容不同类型的控制器实现。

HandlerAdapter:在Spring MVC中,HandlerAdapter 负责将多种类型的请求
处理器(如Controller接口、HttpRequestHandler和SimpleControllerHandlerAdapter)
适配为一个统一的处理流程。视图适配器:Spring MVC使用视图适配器将不同的视图技术(如JSP、
Freemarker、
Thymeleaf)整合到同一模型中,使得控制器可以透明地使用它们。数据访问适配器:Spring通过数据访问适配器简化了对不同数据源的访问,
如JDBC、Hibernate、JPA等,使得业务逻辑可以从具体的数据访问技术中解耦。

多媒体播放器示例

在这个示例中,我们有一个 MediaPlayer 接口和一个实现了 MediaPlayer 接口的具体类 AudioPlayer。AudioPlayer 默认可以播放 mp3 格式的音频文件。

我们还有另一个接口 AdvancedMediaPlayer 和实现了 AdvancedMediaPlayer 接口的具体类。这些类可以播放 vlc 和 mp4 格式的文件。

我们希望 AudioPlayer 也能播放其他格式的音频。为了实现这一点,我们创建了一个适配器类 MediaAdapter,它实现了 MediaPlayer 接口,并使用 AdvancedMediaPlayer 对象来播放所需的格式。

AudioPlayer 使用适配器类 MediaAdapter 并传递它所需的音频类型,而不需要知道实际上哪个类可以播放所需的格式。AdapterPatternDemo(我们的演示类)将使用 AudioPlayer 类来播放各种格式的音频。

在这里插入图片描述
步骤 1:
创建媒体播放器和高级媒体播放器的接口。

public interface MediaPlayer {public void play(String audioType, String fileName);}
public interface AdvancedMediaPlayer {public void playVlc(String fileName);public void playMp4(String fileName);
}

步骤 2:
创建实现 AdvancedMediaPlayer 接口的具体类。

public class VlcPlayer implements AdvancedMediaPlayer{@Overridepublic void playVlc(String fileName) {System.out.println("播放 VLC 文件。名称: " + fileName);}@Overridepublic void playMp4(String fileName) {// 无操作}}
public class Mp4Player implements AdvancedMediaPlayer {@Overridepublic void playVlc(String fileName) {// 无操作}@Overridepublic void playMp4(String fileName) {System.out.println("播放 MP4 文件。名称: " + fileName);}}

步骤 3:
创建实现 MediaPlayer 接口的适配器类。

public class MediaAdapter implements MediaPlayer{AdvancedMediaPlayer advancedMusicPlayer;public MediaAdapter(String audioType){if(audioType.equalsIgnoreCase("vlc") ){advancedMusicPlayer = new VlcPlayer();} else if (audioType.equalsIgnoreCase("mp4")){advancedMusicPlayer = new Mp4Player();}}@Overridepublic void play(String audioType, String fileName) {if(audioType.equalsIgnoreCase("vlc")){advancedMusicPlayer.playVlc(fileName);} else if(audioType.equalsIgnoreCase("mp4")){advancedMusicPlayer.playMp4(fileName);}}
}

步骤 4:
创建实现 MediaPlayer 接口的具体类。

public class AudioPlayer implements MediaPlayer {MediaAdapter mediaAdapter;@Overridepublic void play(String audioType, String fileName) {// 内置支持播放 mp3 音乐文件if(audioType.equalsIgnoreCase("mp3")){System.out.println("播放 mp3 文件。名称: " + fileName);}// mediaAdapter 提供支持播放其他文件格式else if(audioType.equalsIgnoreCase("vlc") || audioType.equalsIgnoreCase("mp4")){mediaAdapter = new MediaAdapter(audioType);mediaAdapter.play(audioType, fileName);}else {System.out.println("无效媒体。" + audioType + " 格式不支持");}}}

步骤 5:
使用 AudioPlayer 来播放不同类型的音频格式。

public class AdapterPatternDemo {public static void main(String[] args) {AudioPlayer audioPlayer = new AudioPlayer();audioPlayer.play("mp3", "beyond the horizon.mp3");audioPlayer.play("mp4", "alone.mp4");audioPlayer.play("vlc", "far far away.vlc");audioPlayer.play("avi", "mind me.avi");}
}

在这里插入图片描述

代码地址

23种设计模式相关代码后续会逐步提交到github上,方便学习,欢迎指点:
代码地址
https://github.com/RuofeiSun/lf-23Pattern

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/212760.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JavaSE基础50题:11. 输出一个整数的每一位

概述 输出一个整数的每一位。 如:1234的每一位是4,3,2,1 。 个位:1234 % 10 4 十位:1234 / 10 123 123 % 10 3 百位:123 / 10 12 12 % 10 2 千位: 12 / 10 1 代码 ublic sta…

yolo目标检测+目标跟踪+车辆计数+车辆分割+车道线变更检测+速度估计

这个项目使用YOLO进行车辆检测,使用SORT(简单在线实时跟踪器)进行车辆跟踪。该项目实现了以下任务: 车辆计数车道分割车道变更检测速度估计将所有这些详细信息转储到CSV文件中 车辆计数是指在道路上安装相应设备,通过…

Linux文件部分知识

目录 认识inode 如何理解创建一个空文件? 如何理解对文件写入信息? 如何理解删除一个文件? 为什么拷贝文件的时候很慢,而删除文件的时候很快? 如何理解目录 ​编辑 文件的三个时间 ​编辑 Access: …

【文件上传系列】No.1 大文件分片、进度图展示(原生前端 + Node 后端 Koa)

分片(500MB)进度效果展示 效果展示,一个分片是 500MB 的 分片(10MB)进度效果展示 大文件分片上传效果展示 前端 思路 前端的思路:将大文件切分成多个小文件,然后并发给后端。 页面构建 先在页…

超大规模集成电路设计----FPGA时序模型及FSM的设计(八)

本文仅供学习,不作任何商业用途,严禁转载。绝大部分资料来自----数字集成电路——电路、系统与设计(第二版)及中国科学院段成华教授PPT 超大规模集成电路设计----RTL级设计之FSM(八) 7.1 CPLD的时序模型7.1.1 XPLA3 时序模型7.1.…

电话卡Giffgaff激活

Giffgaff是一家总部位于英国的移动电话公司。作为一家移动虚拟网络电信运营商,Giffgaff使用O2的网络,是O2的全资子公司,成立于2009年11月25日。 Giffgaff与传统的移动电话运营商不同,区别在于其用户也可以参与公司的部分运营&…

鸿蒙原生应用开发——分布式数据对象

01、什么是分布式数据对象 在可信组网环境下,多个相互组网认证的设备将各自创建的对象加入同一个 sessionId,使得加入的多个数据对象之间可以同步数据,也就是说,当某一数据对象属性发生变更时,其他数据对象会检测到这…

Theamleaf导出pdf模版编写(原始th/td编写表格)

需求&#xff1a;简单的theamleaf编写表格就是简单的th/td&#xff0c;新需求是导出的模版是学员table表&#xff0c;每个项目的学员数量是不定的&#xff0c;所以用到 <tr th:each"item,start:${studentList}"> 所有代码&#xff1a; <!DOCTYPE html>…

离线数仓构建案例一

数据采集 日志数据&#xff08;文件&#xff09;到Kafka 自己写个程序模拟一些用户的行为数据&#xff0c;这些数据存在一个文件夹中。 接着使用flume监控采集这些文件&#xff0c;然后发送给kafka中待消费。 1、flume采集配置文件 监控文件将数据发给kafka的flume配置文件…

GateWay的路由与全局过滤器

1.断言工厂 我们在配置文件中写的断言规则只是字符串&#xff0c;这些字符串会被Predicate Factory读取并处理&#xff0c;转变为路由判断的条件 例如Path/user/**是按照路径匹配&#xff0c;这个规则是由 org.springframework.cloud.gateway.handler.predicate.PathRoutePr…

Linux查看命令的绝对路径

linux查看命令的绝对路径 在Linux中&#xff0c;可以使用以下命令来查看命令的绝对路径&#xff1a; 1、which 命令名 例如&#xff0c;要查看chronyc命令的绝对路径&#xff0c;可以运行&#xff1a; which chronyc 2、whereis 命令名 例如&#xff0c;要查看chronyc命令…

thinkphp lists todo

来由&#xff1a; 数据库的这个字段我想返回成&#xff1a; 新奇的写法如下&#xff1a; 逻辑层的代码&#xff1a; public function goodsDetail($goodId){$detail $this->good->where(id, $goodId)->hidden([type_params,user_id])->find();if (!$detail) {ret…

数字化和数智化一字之差,究竟有何异同点?

在2023杭州云栖大会的一展台内&#xff0c;桌子上放着一颗番茄和一个蛋糕&#xff0c;一旁的机器人手臂融入“通义千问”大模型技术后&#xff0c;变得会“思考”&#xff1a;不仅能描述“看”到了什么&#xff0c;还能确认抓取的是番茄而不是蛋糕。 “传统的机械臂通常都只能基…

【C语言】7-32 刮刮彩票 分数 20

7-32 刮刮彩票 分数 20 全屏浏览题目 切换布局 作者 DAI, Longao 单位 杭州百腾教育科技有限公司 “刮刮彩票”是一款网络游戏里面的一个小游戏。如图所示&#xff1a; 每次游戏玩家会拿到一张彩票&#xff0c;上面会有 9 个数字&#xff0c;分别为数字 1 到数字 9&#xf…

windows系统nodeJs报错node-sass npm ERR! command failed

报错信息 npm WARN deprecated request2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142 npm WARN deprecated tar2.2.2: This version of tar is no longer supported, and will not receive security updates. Please upgrade asa…

利用R语言heatmap.2函数进行聚类并画热图

数据聚类然后展示聚类热图是生物信息中组学数据分析的常用方法&#xff0c;在R语言中有很多函数可以实现&#xff0c;譬如heatmap,kmeans等&#xff0c;除此外还有一个用得比较多的就是heatmap.2。最近在网上看到一个笔记文章关于《一步一步学heatmap.2函数》&#xff0c;在此与…

vscode如何在没有网络的情况下安装插件

vscode如何在没有网络的情况下安装插件 start 遇到没有网络的电脑&#xff0c;无法直接从插件市场安装vscode的插件。写一下 vscode 插件离线安装的方法. 解决方案 目标电脑没有可以安装插件的网络&#xff0c;那我们只能在有网络的环境下载好我们的插件。然后拷贝软件到无…

智能优化算法应用:基于战争策略算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于战争策略算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于战争策略算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.战争策略算法4.实验参数设定5.算法结果6.参考…

服务器数据恢复—重装系统导致XFS文件系统分区丢失的数据恢复案例

服务器数据恢复环境&#xff1a; 服务器使用磁盘柜RAID卡搭建了一组riad5磁盘阵列。服务器上层分配了一个LUN&#xff0c;划分了两个分区&#xff1a;sdc1分区和sdc2分区。通过LVM扩容的方式&#xff0c;将sdc1分区加入到了root_lv中&#xff1b;sdc2分区格式化为XFS文件系统。…

【洛谷】更换头像

错误展示 今天换头像的时候发现一直换不了&#xff0c;即使显示修改成功&#xff0c;然后我等了半个多小时也还没换好 解决办法 上传成功头像后&#xff0c;按ctrl F5 结果 更新成功&#xff01;