适配器模式 rust和java的实现
文章目录
- 适配器模式
- 介绍
- 何时使用
- 应用实例
- 优点
- 缺点
- 使用场景
- 实现
- java实现
- rust 实现
- rust代码仓库
适配器模式
适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。
这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。举个真实的例子,读卡器是作为内存卡和笔记本之间的适配器。您将内存卡插入读卡器,再将读卡器插入笔记本,这样就可以通过笔记本来读取内存卡。
介绍
- 意图:将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
- 主要解决:主要解决在软件系统中,常常要将一些"现存的对象"放到新的环境中,而新环境要求的接口是现对象不能满足的。
- 关键代码:适配器继承或依赖已有的对象,实现想要的目标接口。
何时使用
1、系统需要使用现有的类,而此类的接口不符合系统的需要。
2、想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作,这些源类不一定有一致的接口。
3、通过接口转换,将一个类插入另一个类系中。(比如老虎和飞禽,现在多了一个飞虎,在不增加实体的需求下,增加一个适配器,在里面包容一个虎对象,实现飞的接口。)
应用实例
1、美国电器 110V,中国 220V,就要有一个适配器将 110V 转化为 220V。
2、在 LINUX 上运行 WINDOWS 程序。
3、JAVA 中的 jdbc。
优点
1、可以让任何两个没有关联的类一起运行。
2、提高了类的复用。
3、增加了类的透明度。
4、灵活性好。
缺点
1、过多地使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。
2.由于 JAVA 至多继承一个类,所以至多只能适配一个适配者类,而且目标类必须是抽象类。
使用场景
有动机地修改一个正常运行的系统的接口,这时应该考虑使用适配器模式。
实现
我们有一个 MediaPlayer 接口和一个实现了 MediaPlayer 接口的实体类 AudioPlayer。默认情况下,AudioPlayer 可以播放 mp3 格式的音频文件。
我们还有另一个接口 AdvancedMediaPlayer 和实现了 AdvancedMediaPlayer 接口的实体类。该类可以播放 vlc 和 mp4 格式的文件。
我们想要让 AudioPlayer 播放其他格式的音频文件。为了实现这个功能,我们需要创建一个实现了 MediaPlayer 接口的适配器类 MediaAdapter,并使用 AdvancedMediaPlayer 对象来播放所需的格式。
AudioPlayer 使用适配器类 MediaAdapter 传递所需的音频类型,不需要知道能播放所需格式音频的实际类。AdapterPatternDemo 类使用 AudioPlayer 类来播放各种格式。
适配器模式的 UML 图
java实现
步骤 1
为媒体播放器和更高级的媒体播放器创建接口。
MediaPlayer.java
public interface MediaPlayer {public void play(String audioType, String fileName);
}
AdvancedMediaPlayer.java
public interface AdvancedMediaPlayer { public void playVlc(String fileName);public void playMp4(String fileName);
}
步骤 2
创建实现了 AdvancedMediaPlayer 接口的实体类。
VlcPlayer.java
public class VlcPlayer implements AdvancedMediaPlayer{@Overridepublic void playVlc(String fileName) {System.out.println("Playing vlc file. Name: "+ fileName); }@Overridepublic void playMp4(String fileName) {//什么也不做}
}
Mp4Player.java
public class Mp4Player implements AdvancedMediaPlayer{@Overridepublic void playVlc(String fileName) {//什么也不做}@Overridepublic void playMp4(String fileName) {System.out.println("Playing mp4 file. Name: "+ fileName); }
}
步骤 3
创建实现了 MediaPlayer 接口的适配器类。
MediaAdapter.java
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 接口的实体类。
AudioPlayer.java
public class AudioPlayer implements MediaPlayer {MediaAdapter mediaAdapter; @Overridepublic void play(String audioType, String fileName) { //播放 mp3 音乐文件的内置支持if(audioType.equalsIgnoreCase("mp3")){System.out.println("Playing mp3 file. Name: "+ fileName); } //mediaAdapter 提供了播放其他文件格式的支持else if(audioType.equalsIgnoreCase("vlc") || audioType.equalsIgnoreCase("mp4")){mediaAdapter = new MediaAdapter(audioType);mediaAdapter.play(audioType, fileName);}else{System.out.println("Invalid media. "+audioType + " format not supported");}}
}
步骤 5
使用 AudioPlayer 来播放不同类型的音频格式。
AdapterPatternDemo.java
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");}
}
步骤 6
执行程序,输出结果:
Playing mp3 file. Name: beyond the horizon.mp3
Playing mp4 file. Name: alone.mp4
Playing vlc file. Name: far far away.vlc
Invalid media. avi format not supported
rust 实现
use std::error::Error;
// 播放器接口
trait MediaPlayer{fn paly(&mut self,audio_type:String, file_name:String);
}
// 适配器接口
trait AdvancedMediaPlayer {fn play_vlc(&self ,file_name:String);fn play_mp4(&self,file_name:String );
}
// vlc播器放实体类
struct VlcPlayer {}
impl AdvancedMediaPlayer for VlcPlayer {fn play_vlc(&self ,file_name:String) {println!("Playing vlc file. Name: {}",file_name)}fn play_mp4(&self,file_name:String ) {todo!()}
}
// MP4播放器实体类
struct Mp4Player {}
impl AdvancedMediaPlayer for Mp4Player {fn play_mp4(&self ,file_name:String) {println!("Playing mp4 file. Name: {}",file_name)}fn play_vlc(&self,file_name:String ) {todo!()}
}
// 播放器适配器实体类
struct MediaAdapter{advanced_music_player:Box<dyn AdvancedMediaPlayer>
}
impl MediaPlayer for MediaAdapter {fn paly(&mut self,audio_type:String, file_name:String) {match &audio_type as &str{"vlc"=> self.advanced_music_player.play_vlc(file_name),"mp4"=>self.advanced_music_player.play_mp4(file_name),_ =>println!("不支持此格式文件")}}
}
impl MediaAdapter {fn new (audio_type:String )->Result<MediaAdapter,Box<dyn Error>>{//进行字符产匹配match &audio_type as &str{"vlc"=> Ok(MediaAdapter{advanced_music_player:Box::new(VlcPlayer{})}),"mp4"=>Ok(MediaAdapter{advanced_music_player:Box::new(Mp4Player{})}),_ =>Err(panic!("输入运行格式错误"))}}
}
struct AudioPlayer{media_adapter:MediaAdapter
}
impl AudioPlayer {fn new()->AudioPlayer{AudioPlayer{media_adapter:MediaAdapter { advanced_music_player:Box::new(Mp4Player{})}}}
}
impl MediaPlayer for AudioPlayer {fn paly(&mut self,audio_type:String, file_name:String) {match &audio_type as &str{"vlc"|"mp4"=>{self.media_adapter=MediaAdapter::new(audio_type.clone()).unwrap();self.media_adapter.paly(audio_type, file_name);},_ =>println!("不支持此格式文件")}}
}fn main() {let mut audioPlayer =AudioPlayer::new();// 进行不同文件的播放测试audioPlayer.paly(String::from("mp3"), String::from("beyond the horizon.mp3"));audioPlayer.paly(String::from("mp4"), String::from("alone.mp4"));audioPlayer.paly(String::from("mp4"), String::from("far far away.vlc"));
}
rust代码仓库
https://github.com/onenewcode/design.git
本教程项目在bin文件夹下的singleobject.rs文件中
相关文章:

适配器模式 rust和java的实现
文章目录 适配器模式介绍何时使用应用实例优点缺点使用场景 实现java实现rust 实现 rust代码仓库 适配器模式 适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能…...

竞赛 题目:垃圾邮件(短信)分类 算法实现 机器学习 深度学习 开题
文章目录 1 前言2 垃圾短信/邮件 分类算法 原理2.1 常用的分类器 - 贝叶斯分类器 3 数据集介绍4 数据预处理5 特征提取6 训练分类器7 综合测试结果8 其他模型方法9 最后 1 前言 🔥 优质竞赛项目系列,今天要分享的是 基于机器学习的垃圾邮件分类 该项目…...

wpf devexpress项目中添加GridControl绑定数据
本教程讲解了如何添加GridControl到wpf项目中并且绑定数据 原文地址Lesson 1 - Add a GridControl to a Project and Bind it to Data | WPF Controls | DevExpress Documentation 1、使用 DevExpress Template Gallery创建一个新的空白mvvm应用程序,这个项目包括了…...

2023亚太杯数学建模A题思路解析
文章目录 0 赛题思路1 竞赛信息2 竞赛时间3 建模常见问题类型3.1 分类问题3.2 优化问题3.3 预测问题3.4 评价问题 4 建模资料5 最后 0 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 1 竞赛信息 2023年第十三…...

Spark3.0中的AOE、DPP和Hint增强
1 Spark3.0 AQE Spark 在 3.0 版本推出了 AQE(Adaptive Query Execution),即自适应查询执行。AQE 是 Spark SQL 的一种动态优化机制,在运行时,每当 Shuffle Map 阶段执行完毕,AQE 都会结合这个阶段的统计信…...

算法笔记-第五章-质因子分解
算法笔记-第五章-质因子分解 小试牛刀质因子2的个数丑数 质因子分解最小最大质因子约数个数 小试牛刀 质因子2的个数 #include<cstdio> int main() {int n; scanf_s("%d", &n); int count 0; while (n % 2 0) {count; n / 2; }printf("%…...

适用于WPF的设计模式
适用于WPF的设计模式 讨论“XAML能不能写逻辑代码”这个问题。我发现这是个有歧义的问题。这个问题可以有两种意思: XAML能不能用来写逻辑代码? XAML文件里能不能包含逻辑代码? 对于第一种意思——XAML是一种声明性语言,就是用来…...
C++与多态
多态的本质是允许对象以其实际类型的行为方式来操作,而不仅仅是其静态类型所声明的方式。 多态是面向对象编程中的一种核心概念,它允许对象根据其具体类型执行相应的操作,而不是其声明的类型。我们可以使用一个经典的动物的例子来说明这一点。…...

ios 对话框UIAlertController放 tableview
//强弱引用 #define kWeakSelf(type)__weak typeof(type)weak##type type; -(void) showUIAlertTable {kWeakSelf(self)UIAlertController *alert [UIAlertController alertControllerWithTitle:NSLocalizedString("select_stu", nil) message:nil prefer…...
警告:新版Outlook会向微软发送密码、邮件和其他数据
新的免费Outlook会将敏感数据发送给 Microsoft。 在没有通知或询问的情况下,Microsoft 授予自己对新 Outlook 用户的 IMAP 和 SMTP 访问数据的完全访问权限。也就是说,当用户设置 IMAP 帐户时,新的 Outlook 会将访问数据和服务器信息发送给 …...
数据结构C语言--基础实验
实验1 线性表的顺序实现 1.!顺序表的倒置 /**********************************/ /*文件名称:lab1-01.c */ /**********************************/ /*基于sequlist.h中定义的顺序表,编写算法函数reverse(sequence_list *L)&…...

wireshark抓包并进行Eigrp网络协议分析
路由协议 Eigrp EIGRP:Enhanced Interior Gateway Routing Protocol 即 增强内部网关路由协议。也翻译为 加强型内部网关路由协议。 EIGRP是Cisco公司的私有协议(2013年已经公有化)。 EIGRP结合了链路状态和距离矢量型路由选择协议的Cisco专用协议&a…...

力扣刷题-二叉树-二叉树的层序遍历(相关题目总结)
思路 层序遍历一个二叉树。就是从左到右一层一层的去遍历二叉树。这种遍历的方式和我们之前讲过的都不太一样。 需要借用一个辅助数据结构即队列来实现,队列先进先出,符合一层一层遍历的逻辑,而用栈先进后出适合模拟深度优先遍历也就是递归的…...
fundamental notes in 3D math
平面方程 a x b y c z d axbycz d axbyczd, 法向量 a , b , c a,b,c a,b,c, 点到平面的距离为 d / s q r t ( a 2 b 2 c 2 ) d / sqrt(a^2 b^2 c^2) d/sqrt(a2b2c2) , 距离可为正, 为负, 为正表示跟法向量方向一致, 为负表示相反 点 ( x o , y o , z o ) (x_o, y_o, z…...

【Java 进阶篇】JQuery DOM操作:舞动网页的属性魔法
在前端的舞台上,属性操作是我们与HTML元素进行互动的关键步骤之一。而JQuery,这位前端开发的巫师,通过简洁而强大的语法,为我们提供了便捷的属性操作工具。在这篇博客中,我们将深入研究JQuery DOM操作中的属性操作&…...

腾讯云5年云服务器还有吗?腾讯云5年时长服务器入口在哪?
如果你是一名企业家或者是一个热衷于数字化转型的创业者,那么腾讯云最近推出的一项优惠活动绝对不会让你无动于衷。现在,腾讯云正在大力推广一项5年特价云服务器活动,只需要花费3879元,你就可以享受到腾讯云提供的优质服务。 腾讯…...
odoo在iot领域的发展情况
Odoo 是一个全面的集成商业管理软件套装,主要提供企业资源规划 (ERP)、客户关系管理 (CRM)、电子商务、会计、库存管理等功能。在 IoT(物联网)领域,Odoo 侧重于通过提供一个中心化的平台来整合多方面的业务流程,包括生…...
Paas-云原生-容器-编排-持续部署
了解云原生 云原生架构让企业的基础设施,从简单的资源池化,转向以应用为中心,为应用赋能的敏捷、自运维、安全的云原生基础设施。以应用为中心的云原生基础设置,可以支持多种类型的应用,如微服务应用,中间件应用和AI 应用;可以提升应用交付效率,简化应用管理的复杂度;…...

sass 生成辅助色
背景 一个按钮往往有 4 个状态。 默认状态hover鼠标按下禁用状态 为了表示这 4 个状态,需要设置 4 个颜色来提示用户。 按钮类型一般有 5 个: 以 primary 类型按钮为例,设置它不同状态下的颜色: <button class"btn…...

DevEco Studio开发工具下载、安装(HarmonyOS开发)_For Mac
一、说明 初学HarmonyOS开发,DevEco Studio开发工具的安装和使用是必须的。 (注:不多废话,跟着下面流程操作下载、安装DevEco Studio即可。) 二、下载DevEco Studio 1.官网下载地址: https://developer.…...

【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...

自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...

关于easyexcel动态下拉选问题处理
前些日子突然碰到一个问题,说是客户的导入文件模版想支持部分导入内容的下拉选,于是我就找了easyexcel官网寻找解决方案,并没有找到合适的方案,没办法只能自己动手并分享出来,针对Java生成Excel下拉菜单时因选项过多导…...
离线语音识别方案分析
随着人工智能技术的不断发展,语音识别技术也得到了广泛的应用,从智能家居到车载系统,语音识别正在改变我们与设备的交互方式。尤其是离线语音识别,由于其在没有网络连接的情况下仍然能提供稳定、准确的语音处理能力,广…...

第一篇:Liunx环境下搭建PaddlePaddle 3.0基础环境(Liunx Centos8.5安装Python3.10+pip3.10)
第一篇:Liunx环境下搭建PaddlePaddle 3.0基础环境(Liunx Centos8.5安装Python3.10pip3.10) 一:前言二:安装编译依赖二:安装Python3.10三:安装PIP3.10四:安装Paddlepaddle基础框架4.1…...