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

Java设计模式——适配器模式

目录

模式动机

模式定义

模式结构

代码分析

模式分析

实例

优点

缺点

适用环境

模式应用

模式扩展

总结


模式动机

在软件开发过程中,经常会遇到需要使用已有类的功能,但这些类的接口不符合当前系统的需求,或者需要将不同的类的接口统一起来的情况。适配器模式正是为了解决这类问题而设计的。通过适配器模式,可以将一个类的接口转换成另一个接口,从而使原本不兼容的类可以一起工作。

模式定义

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

模式结构

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

  • Target(目标接口):定义客户端所期待的接口。
  • Adaptee(适配者):已经存在的类,需要适配的类,它提供了一些有用的方法,但接口不符合客户端的要求。
  • Adapter(适配器):适配器类,它实现了目标接口,并将请求转发给适配者类。

类适配器

类适配器通过继承适配者类来实现目标接口。

对象适配器

对象适配器通过在适配器类中包含适配者对象的实例来实现目标接口。

代码分析

类适配器示例

// 目标接口
interface Target {void request();
}// 适配者类
class Adaptee {public void specificRequest() {System.out.println("Adaptee specificRequest");}
}// 类适配器
class ClassAdapter extends Adaptee implements Target {@Overridepublic void request() {specificRequest();}
}// 客户端
public class Client {public static void main(String[] args) {Target target = new ClassAdapter();target.request();}
}

对象适配器示例

// 目标接口
interface Target {void request();
}// 适配者类
class Adaptee {public void specificRequest() {System.out.println("Adaptee specificRequest");}
}// 对象适配器
class ObjectAdapter implements Target {private Adaptee adaptee;public ObjectAdapter(Adaptee adaptee) {this.adaptee = adaptee;}@Overridepublic void request() {adaptee.specificRequest();}
}// 客户端
public class Client {public static void main(String[] args) {Adaptee adaptee = new Adaptee();Target target = new ObjectAdapter(adaptee);target.request();}
}

模式分析

适配器模式的核心思想是通过适配器类来转换接口,使得原本不兼容的类可以一起工作。适配器模式有两种实现方式:类适配器和对象适配器。类适配器通过继承适配者类来实现目标接口,而对象适配器通过在适配器类中包含适配者对象的实例来实现目标接口。

实例

假设有一个旧的音频播放器类,只能播放 MP3 格式的音频文件。现在需要扩展该播放器,使其能够播放新的音频格式,如 VLC 和 MP4。可以通过适配器模式来实现这一需求。

// 目标接口
interface MediaPlayer {void play(String audioType, String fileName);
}// 适配者类:VLC 播放器
class VlcPlayer {public void playVlc(String fileName) {System.out.println("Playing vlc file. Name: " + fileName);}
}// 适配者类:MP4 播放器
class Mp4Player {public void playMp4(String fileName) {System.out.println("Playing mp4 file. Name: " + fileName);}
}// 对象适配器:音频播放器适配器
class MediaAdapter implements MediaPlayer {private MediaPlayer 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")) {((VlcPlayer) advancedMediaPlayer).playVlc(fileName);} else if (audioType.equalsIgnoreCase("mp4")) {((Mp4Player) advancedMediaPlayer).playMp4(fileName);}}
}// 原始音频播放器
class AudioPlayer implements MediaPlayer {@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 mediaAdapter = new MediaAdapter(audioType);mediaAdapter.play(audioType, fileName);} else {System.out.println("Invalid media. " + audioType + " format not supported");}}
}// 客户端
public class Client {public static void main(String[] args) {AudioPlayer audioPlayer = new AudioPlayer();audioPlayer.play("mp3", "beyond.mp3");audioPlayer.play("mp4", "alone.mp4");audioPlayer.play("vlc", "far far away.vlc");audioPlayer.play("avi", "mind.mind");}
}

优点

  • 提高类的透明性和复用性:通过适配器模式,可以将已有的类或接口适配成新的接口,提高类的透明性和复用性。
  • 灵活性:适配器模式使得系统更容易扩展,可以在不修改原有代码的情况下引入新的适配器类。
  • 开闭原则:符合开闭原则,可以在不修改现有代码的情况下引入新的适配器类。

缺点

  • 增加系统复杂性:适配器模式会增加系统的复杂性,因为需要引入额外的适配器类。
  • 类的膨胀:如果需要适配的类很多,可能会导致适配器类的数量增加,从而增加系统的维护成本。

适用环境

  • 系统需要使用现有的类,但其接口不符合系统的需求
  • 希望增加系统的灵活性和可扩展性
  • 需要将不同的类的接口统一起来

模式应用

适配器模式在实际开发中应用广泛,特别是在以下场景中:

  • 遗留系统集成:将旧的系统或类集成到新的系统中。
  • 框架扩展:在不修改框架源码的情况下,通过适配器模式扩展框架的功能。
  • 第三方库集成:将第三方库的接口适配成系统需要的接口。

模式扩展

适配器模式可以与其他设计模式结合使用,例如:

  • 工厂模式:可以使用工厂模式来创建适配器对象,从而进一步提高系统的灵活性。
  • 装饰器模式:可以在适配器的基础上使用装饰器模式,进一步增强适配后的对象的功能。

总结

适配器模式通过适配器类将一个类的接口转换成另一个接口,使得原本不兼容的类可以一起工作。适配器模式分为类适配器和对象适配器两种实现方式。适配器模式提高了类的透明性和复用性,增加了系统的灵活性和可扩展性,但在某些情况下会增加系统的复杂性和维护成本。适配器模式适用于需要将不同类的接口统一起来的场景,广泛应用于系统集成、框架扩展和第三方库集成等场景中。

相关文章:

Java设计模式——适配器模式

目录 模式动机 模式定义 模式结构 代码分析 模式分析 实例 优点 缺点 适用环境 模式应用 模式扩展 总结 模式动机 在软件开发过程中,经常会遇到需要使用已有类的功能,但这些类的接口不符合当前系统的需求,或者需要将不同的类的接…...

docker compose入门6—如何挂载卷

在 Docker Compose 中,可以通过 volumes 字段将宿主机的文件或目录挂载到容器中。这样可以实现数据持久化、共享数据或配置等。以下是一些常见的挂载方式和示例。 1. 挂载单个文件 如果你想将宿主机上的一个特定文件挂载到容器中,可以使用以下格式&…...

linux 环境下 docker 镜像获取失败, 重新设置docker镜像下载地址

1.查询镜像地址 https://hub.atomgit.com/repos/amd64/openjdk 2.docker file FROM hub.atomgit.com/amd64/openjdk:21-rc-jdk COPY xxxx.jar xxxx.jar EXPOSE xxxxx ENTRYPOINT ["java","-jar","-Xmx200M","-agentlib:jdwptransportdt_…...

【React】setState 是怎么记住上一个状态值的?

在 React 中,setState 通过 React 内部的状态管理机制来记住上一个状态值。即使每次组件重新渲染时,函数组件会被重新执行,React 仍能通过其内部的状态管理系统保持和追踪组件的状态变化。下面详细解释其工作原理: 1. setState 的…...

linux批量删文件

在 Linux 中,可以使用命令行工具来批量删除文件。以下是一些常用的方法: 使用 rm 命令 rm 是一个用于删除文件和目录的命令。使用此命令时应谨慎,因为删除操作是不可逆的。 删除特定类型的文件 例如,要删除当前目录下所有的 .tx…...

Kubernetes(K8s)的简介

一、Kubernetes的简介 1 应用部署方式演变 在部署应用程序的方式上,主要经历了三个阶段: 传统部署:互联网早期,会直接将应用程序部署在物理机上 优点:简单,不需要其它技术的参与 缺点:不能为应…...

线性查找法 ← Python实现

【线性查找法】 线性查找法顺序地将关键元素 key 和列表中的每一个元素进行比较。它连续这样做,直到这个关键字匹配列表中的某个元素,或者在没有找到匹配元素时已经查找完整个列表。如果找到一个匹配元素,那么线性查找将返回匹配在列表中的下…...

view deign 和 vue2 合并单元格的方法

1.vue版本和view design 版本 {"vue": "^2.6.11","view-design": "^4.7.0", }2.Data中定义数据 spanArr: [], // 某一列下需要合并的行数 pos: 0// 索引// 注意点: 在获取列表前,需要重置 this.spanArr [] 注…...

Arduino UNO R3自学笔记16 之 Arduino的定时器介绍及应用

注意:学习和写作过程中,部分资料搜集于互联网,如有侵权请联系删除。 前言:学习定时器的功能。 1.定时器介绍 定时器也是一种中断,属于软件中断。 它就像一个时钟,可以测量事件的时间间隔。 比如早…...

鸟类数据集,鸟数据集,目标检测class:bird,共一类13000+张图片yolo格式(txt)

鸟类数据集,鸟数据集,目标检测class:bird,共一类13000张图片yolo格式(txt) 鸟类数据集,鸟数据集,目标检测 class:bird,共一类 13000张图片 yolo格式(txt) 鸟…...

透明物体的投射和接收阴影

1、让透明度测试Shader投射阴影 (1)同样我们使用FallBack的形式投射阴影,但是需要注意的是,FallBack的内容为:Transparent / Cutout / VertexLit,该默认Shader中会把裁剪后的物体深度信息写入到 阴影映射纹…...

NL2SQL商业案例详解:AI智能开放搜索 OpenSearch

NL2SQL商业案例详解:AI智能开放搜索 OpenSearch 基于阿里巴巴自主研发的大规模分布式搜索引擎搭建的一站式智能搜索业务开发平台,目前为包括淘宝、天猫在内的阿里集团核心业务提供搜索服务支持。通过内置各行业的查询语义理解、机器学习排序算法等能力,以及充分开放的文本向…...

【万字长文】Word2Vec计算详解(一)

【万字长文】Word2Vec计算详解(一) 写在前面 本文用于记录本人学习NLP过程中,学习Word2Vec部分时的详细过程,本文与本人写的其他文章一样,旨在给出Word2Vec模型中的详细计算过程,包括每个模块的计算过程&a…...

【EXCEL数据处理】000022 案例 保姆级教程,附多个操作案例。EXCEL邮件合并工具

前言:哈喽,大家好,今天给大家分享一篇文章!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 【EXCEL数据处理】000022 案例 保姆级教程,附多个操作案例。…...

第十五周:机器学习笔记

第十五周周报 摘要Abstract一、机器学习1. 各式各样神奇的自注意力机制1.1 Local Attention/Truncated Attention(截断注意力机制)1.2 Stride Attention(跨步注意力机制)1.3 Global Attention(全局注意力机制&#xff…...

Highcharts 散点图

Highcharts 散点图 介绍 Highcharts 是一个流行的 JavaScript 图表库,广泛用于网页上展示动态和交互式的图表。散点图是 Highcharts 提供的一种图表类型,它通过在二维坐标系中展示数据点的分布,来揭示变量之间的关系。散点图特别适用于展示和比较大量的数据点,从而发现数…...

谷粒商城踩坑

1.mysql表名大小写问题(P16) 问题描述:代码要求的是表名大写,但实际上数据库是小写的,就报错: 问题解决:未解决 mysql版本为5.7.44。网上有两种解决方式,但是都解决不了 1.1 解决方…...

构建MySQL健康检查Web应用

构建MySQL健康检查Web应用 在这里将探讨如何将MySQL健康检查功能转换为一个功能完整的Web应用。这个应用允许用户通过简单的Web界面执行MySQL健康检查,并查看详细的结果。我们将逐步介绍代码实现、改进过程以及如何设置和运行这个应用。 1. MySQL健康检查类 首先…...

【LeetCode】每日一题 2024_10_8 旅行终点站(哈希)

前言 每天和你一起刷 LeetCode 每日一题~ LeetCode 启动! 国庆结束了 . . . 力扣的每日一题也来到了终点站 题目:旅行终点站 代码与解题思路 func destCity(paths [][]string) string { // 国庆结束,旅途到了终点// 今天这道题算是一个小…...

Matlab实现海鸥优化算法优化回声状态网络模型 (SOA-ESN)(附源码)

目录 1.内容介绍 2部分代码 3.实验结果 4.内容获取 1内容介绍 海鸥优化算法(Seagull Optimization Algorithm, SOA)是一种受海鸥觅食和飞行行为启发的群体智能优化算法。SOA通过模拟海鸥在空中搜寻食物、聚集和分散的行为模式,来探索和开发…...

看门狗电路设计

看门狗电路设计 看门狗是什么应用架构图TPV6823芯片功能硬件时序图为什么要一般是要保持200个毫秒左右的这种低电平的时间看门狗电路实际应用与条件 看门狗是什么 硬件看门狗芯片,Watch DogTimer,可用于受到电气噪音、电源故障、静电放电等影响(造成软件…...

No.13 笔记 | 网络安全防护指南:从法律法规到技术防御

一、法律法规 《中华人民共和国网络安全法》要点 遵守法律:所有个人和组织在使用网络时,必须遵守宪法和法律,不得利用网络从事危害国家安全等活动。 个人信息保护:禁止非法获取、出售或提供个人信息。若违反但未构成犯罪&#x…...

大数据毕业设计选题推荐-白酒销售数据分析-Python数据可视化-Hive-Hadoop-Spark

✨作者主页:IT研究室✨ 个人简介:曾从事计算机专业培训教学,擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…...

shell脚本写代码

用简单的test语句来判断是否闰年 #! /bin/bash read -p "sd " yearif [ $((year%4)) -eq 0 -a $((year%100)) -ne 0 -o $((year%400)) -eq 0 ]thenecho "是润年"elseecho "不是闰年" fi判断一个数是否为偶数 #! /bin/bash read -p "…...

SLM2104S高压半桥驱动SLM2104SCA-13GTR兼容IR2104 高压、高速的功率MOSFET和IGBT驱动器

SLM2104SCA-13GTR产品概述: SLM2104SCA-13GTR是一款高压、高速的功率MOSFET和IGBT驱动器,它提供相互依存的高边、低边输出驱动信号。采用专有的高压集成电路和锁存免疫CMOS技术,提供可靠的单芯片驱动方案。逻辑输入电平与标准CMOS或LSTTL输出…...

三层网络与三层组网

"三层组网"和"三层网络"虽然名字相似,但它们的含义却有所不同 三层网络 三层网络指的是网络层的概念,它工作在OSI模型的第三层——网络层。网络层的主要功能是通过IP地址进行路由和转发数据包。三层网络设备,如路由器或…...

从0开始下载安装并使用unity

首先我们要在浏览器上找到unity的官网 这一个就是了,我们点进去后是这个界面: 然后我们点击上面这张图的左下角的“下载Unity Hub”,推荐后续安装都装在D盘: 这里他会让我们注册一个账号,如果之前有的话登录就行了&am…...

QT:计算点到线段的垂线段的距离

描述 在Qt中,要计算一个点到一条线段的垂线段的长度(即点到线段上最近点的距离,且这个点是垂直于线段的),你不能直接使用QVector2D::distanceToLine,因为这个方法计算的是点到直线的垂直距离,而…...

经典5级流水线概述

抽象化的流水线结构: 流水线的基本概念 多个任务重叠(并发/并行)执行,但使用不同的资源流水线技术提高整个系统的吞吐率,不能缩短单个任务的执行时间其潜在的加速比=流水线的级数 流水线正常工作的基本条件…...

LSTM模型实现电力数据预测

关于深度实战社区 我们是一个深度学习领域的独立工作室。团队成员有:中科大硕士、纽约大学硕士、浙江大学硕士、华东理工博士等,曾在腾讯、百度、德勤等担任算法工程师/产品经理。全网20多万粉丝,拥有2篇国家级人工智能发明专利。 社区特色&a…...