适配器模式 详解 设计模式

适配器模式

适配器模式是一种结构型设计模式,其主要作用是解决两个不兼容接口之间的兼容性问题。适配器模式通过引入一个适配器来将一个类的接口转换成客户端所期望的另一个接口,从而让原本由于接口不匹配而无法协同工作的类能够协同工作。

结构

适配器模式(Adapter)包含以下主要角色:

  • 目标(Target)接口:当前系统业务所期待的接口,它可以是抽象类或接口。
  • 适配者(Adaptee)类:它是被访问和适配的现存组件库中的组件接口。
  • 适配器(Adapter)类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。

图例:

在这里插入图片描述

AudioPlayer实现了 MediaPlayer 接口,只可以播放 mp3 。实现了 AdvancedMediaPlayer 接口的类则可以播放 vlc 和 mp4 格式的文件。可以创建一个实现了 MediaPlayer 接口的适配器类 MediaAdapter,并使用 AdvancedMediaPlayer 的实现类对象来播放所需的格式。AdapterPatternDemo 类则可以使用 AudioPlayer 类来播放各种格式的音频。

对象适配器模式代码案例:

// 目标接口
interface MediaPlayer {void play(String audioType, String filename);  
}// 适配器接口
interface AdvancedMediaPlayer {void playVlc(String filename);void playMp4(String filename);
}// 适配器类
class MediaAdapter implements MediaPlayer {private AdvancedMediaPlayer advancedMediaPlayer;public MediaAdapter(String audioType) {if (audioType.equalsIgnoreCase("vlc")) {advancedMediaPlayer = new VlcPlayer();} else if (audioType.equalsIgnoreCase("mp4")) {advancedMediaPlayer = new Mp4Player();}}@Overridepublic void play(String audioType, String filename) {if (audioType.equalsIgnoreCase("vlc")) {advancedMediaPlayer.playVlc(filename);} else if (audioType.equalsIgnoreCase("mp4")) {advancedMediaPlayer.playMp4(filename);}}
}// 具体实现类
class AudioPlayer implements MediaPlayer {MediaAdapter mediaAdapter;@Overridepublic void play(String audioType, String filename) {if (audioType.equalsIgnoreCase("mp3")) {System.out.println("Playing mp3 file. Name: " + filename);} 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");}}
}class VlcPlayer implements AdvancedMediaPlayer {@Overridepublic void playVlc(String filename) {System.out.println("Playing vlc file. Name: " + filename);}@Overridepublic void playMp4(String filename) {// Do nothing}
}class Mp4Player implements AdvancedMediaPlayer {@Overridepublic void playVlc(String filename) {// Do nothing}@Overridepublic void playMp4(String filename) {System.out.println("Playing mp4 file. Name: " + filename);}
}// 使用示例
public class Main {public static void main(String[] args) {AudioPlayer audioPlayer = new AudioPlayer();audioPlayer.play("mp3", "song.mp3");audioPlayer.play("vlc", "movie.vlc");audioPlayer.play("mp4", "video.mp4");}
}

适配器模式有类适配器模式和对象适配器模式;这里使用对象适配器模式主要是类适配器模式违背了合成复用原则,它限制了适配器类只能适配一个具体的被适配者类。且Java 不支持多重继承,因此在 Java 中一般使用接口来实现类似的功能

比如下面类适配器,采用的是继承:

// 适配器类(类适配器)
class MediaAdapter extends Mp4Player implements MediaPlayer { @Overridepublic void play(String audioType, String filename) {if (audioType.equalsIgnoreCase("vlc")) {playVlc(filename);} else if (audioType.equalsIgnoreCase("mp4")) {playMp4(filename);}}
}

当然,也有接口适配器模式,不过使用相对较少。当一个接口拥有许多方法,但实现类只需要实现其中一部分方法时,可以使用接口适配器模式,提供一个抽象适配器类实现该接口,并提供默认实现,从而避免实现类需要实现大量空方法。

使用场景:

  • 当需要使用一个已经存在的类,但是它的接口不符合当前需求时,可以考虑使用适配器模式。
  • 当需要复用一些已经存在的类,但是接口与其他类不兼容时,可以考虑使用适配器模式。
  • 当需要创建一个可复用的类,该类可以与不相关或不可预见的类协同工作时,可以考虑使用适配器模式。

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

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

相关文章

想要调用淘宝开放平台API,没有申请应用怎么办?

用淘宝自定义API接口可以访问淘宝开放平台API。 custom-自定义API操作 taobao.custom 公共参数 注册账号获取API请求地址 名称类型必须描述keyString是调用key(必须以GET方式拼接在URL中)secretString是调用密钥api_nameString是API接口名称&#xf…

Docker与虚拟机比较

在对比Docker和虚拟机前,先简单了解下虚拟化,明确Docker和虚拟机分别对应的虚拟化级别,然后对Docker和虚拟机进行比较。需要注意的是,Docker和虚拟机并没有什么可比性,而是Docker使用的容器技术和虚拟机使用的虚拟化技…

【K8S类型系统】一文梳理 K8S 各类型概念之间的关系(GVK/GVR/Object/Schema/RestMapper)

参考 k8s 官方文档 https://kubernetes.io/zh-cn/docs/reference/https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/ 重点 Kubernetes源码学习-kubernetes基础数据结构 - 知乎 重点 Kubernetes类型系统 | 李乾坤的博客 重点 k8s源码学习-三大核心数…

前端学习第二天-html提升

达标要求 了解列表的分类 熟练掌握列表的用法 熟练掌握表格的结构构成 合并单元格 表单的组成 熟练掌握表单控件分类的使用 1.列表 1.1 无序列表 <ul>&#xff1a;定义无序列表&#xff0c;并且只能包含<li>子元素。 <li>&#xff1a;定义列表项&a…

LZO索引文件失效说明

在hive中创建lzo文件和索引时&#xff0c;进行查询时会出现问题.hive的默认输入格式是开启小文件合并的&#xff0c;会把索引也合并进来。所以要关闭hive小文件合并功能&#xff01;

Matlab:元胞自动机

元胞自动机是一种基于离散空间的动态系统&#xff0c;由许多简单单元按照某些规则进行相互作用和演化而形成的复杂结构。元胞自动机可以用于模拟物理、生物、社会等领域的现象&#xff0c;以及进行优化、图像处理、噪声生成等方面的应用。 例1&#xff1a;生命游戏 nextState…

maven项目报错Cannot resolve plugin org.apache.maven.plugins:maven-war-plugin:2.2

如果IDEA整合maven没有问题&#xff0c;还是报这个错误&#xff0c;很大可能是由于在下载过程中存在网络问题&#xff0c;导致文件下载一半而停止&#xff0c;但是已经在仓库中存在这个文件夹&#xff0c;解决方法是删除文件夹重新下载即可。 删除本地仓库下的\org\apache\mav…

(算法)位运算

常见的位运算符&#xff1a; 给定一个数n判断他的二进制第x位是0还是1 把第x位修改为1 因为是只是修改n的某个位置&#xff0c;所以不应该移动改变n 既然修改为1&#xff0c;那么就要想到 | 运算符 把第x位修改为0 因为修改为0,所以要用&运算符 位图思想 判定字符串…

二维码门楼牌管理系统技术服务的深度解析

文章目录 前言一、标准地址名称的定义与重要性二、二维码门楼牌管理系统的核心技术三、标准地址名称在二维码门楼牌管理中的应用四、二维码门楼牌管理系统的优势与挑战五、展望未来 前言 在数字化浪潮中&#xff0c;二维码门楼牌管理系统以其高效、便捷的特性&#xff0c;正逐…

【一】【算法分析与设计】基础测试

排列式 题目描述 7254是一个不寻常的数&#xff0c;因为它可以表示为7254 39 x 186&#xff0c;这个式子中1~9每个数字正好出现一次 输出所有这样的不同的式子&#xff08;乘数交换被认为是相同的式子&#xff09; 结果小的先输出&#xff1b;结果相同的&#xff0c;较小的乘…

js 实战小案例

实战 时间 js 格式化时间 <script type"text/javascript">function formatDate(date) { let year date.getFullYear(); let month String(date.getMonth() 1).padStart(2, 0); // getMonth() 返回的月份是从0开始的&#xff0c;所以要加1&#xff0c;并…

【go从入门到精通】go包,内置类型和初始化顺序

大家好&#xff0c;这是我给大家准备的新的一期专栏&#xff0c;专门讲golang&#xff0c;从入门到精通各种框架和中间件&#xff0c;工具类库&#xff0c;希望对go有兴趣的同学可以订阅此专栏。 go基础 。 Go文件名&#xff1a; 所有的go源码都是以 ".go" 结尾&…

Mamba 环境安装:causal-conv1d和mamba-ssm报错解决办法

问题描述&#xff1a; 在执行命令 pip install causal_conv1d 和 mamba_ssm 出错&#xff1a; 解决方案&#xff1a; 1、使用网友配置好的Docker环境&#xff0c;参考&#xff1a;解决causal_conv1d和mamba_ssm无法安装 -&#xff1e; 直接使用Mamba基础环境docker镜像 DockH…

java实现图片转pdf,并通过流的方式进行下载(前后端分离)

首先需要导入相关依赖&#xff0c;由于具体依赖本人也不是记得很清楚了&#xff0c;所以简短的说一下。 iText&#xff1a;PDF 操作库&#xff0c;用于创建和操作 PDF 文件。可通过 Maven 或 Gradle 引入 iText 依赖。 MultipartFile&#xff1a;Spring 框架中处理文件上传的类…

一台工控机的能量

使用Docker搭建EPICS的IOC记录 Zstack EPICS Archiver在小课题组的使用经验 以前电子枪调试&#xff0c;用一台工控机跑起束测后台&#xff0c;这次新光源用的电子枪加工回来又是测试&#xff0c;又是用一台工控机做起重复的事&#xff0c;不过生命在于折腾&#xff0c;重复的…

stm32——hal库学习笔记(IIC)

一、IIC总线协议介绍&#xff08;掌握&#xff09; 二、AT24C02介绍&#xff08;了解&#xff09; 三、AT24C02读写时序&#xff08;掌握&#xff09; 四、AT24C02驱动步骤&#xff08;掌握&#xff09; 五、编程实战&#xff08;掌握&#xff09; myiic.c #include "./B…

汽车虚拟仿真技术的实现、应用和未来

汽车虚拟仿真技术是一种利用计算机模拟汽车运行的技术&#xff0c;以实现对汽车行为的分析、评估和改进。汽车虚拟仿真技术是汽车工业中重要的开发设计和测试工具&#xff0c;可以大大缩短产品研发周期、降低研发成本和提高产品质量。本文将从汽车虚拟仿真技术的实现过程、应用…

Ubuntu18.04 系统上配置并运行SuperGluePretrainedNetwork(仅使用CPU)

SuperGlue是Magic Leap在CVPR 2020上展示的研究项目&#xff0c;它是一个图神经网络&#xff08;Graph Neural Network&#xff09;和最优匹配层&#xff08;Optimal Matching layer&#xff09;的结合&#xff0c;训练用于对两组稀疏图像特征进行匹配。这个项目提供了PyTorch代…

前端的文字的字体应该如何设置

要设置文字的字体&#xff0c;在CSS中使用font-family属性。这个属性可以接受一个或多个字体名称作为其值&#xff0c;浏览器会按照列表中的顺序尝试使用这些字体渲染文本。如果第一个字体不可用&#xff0c;浏览器会尝试使用列表中的下一个字体&#xff0c;依此类推。 字体设…

iOS消息发送流程

Objc的方法调用基于消息发送机制。即Objc中的方法调用&#xff0c;在底层实际都是通过调用objc_msgSend方法向对象消息发送消息来实现的。在iOS中&#xff0c; 实例对象的方法主要存储在类的方法列表中&#xff0c;类方法则是主要存储在原类中。 向对象发送消息&#xff0c;核心…