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

06-Java适配器模式 ( Adapter Pattern )

原型模式

    • 摘要
    • 实现
    • 范例

  • 适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁

  • 适配器模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能

举个真实的例子,读卡器是作为内存卡和笔记本之间的适配器。您将内存卡插入读卡器,再将读卡器插入笔记本,这样就可以通过笔记本来读取内存卡

适配器模式属于结构型模式,它结合了两个独立接口的功能

摘要

1. 意图

将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作

2. 主要解决

主要解决在软件系统中,常常要将一些”现存的对象”放到新的环境中,而新环境要求的接口是现对象不能满足的

3. 何时使用

  1. 系统需要使用现有的类,而此类的接口不符合系统的需要;
  2. 想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作,这些源类不一定有一致的接口;
  3. 通过接口转换,将一个类插入另一个类系中(比如老虎和飞禽,现在多了一个飞虎,在不增加实体的需求下,增加一个适配器,在里面包容一个虎对象,实现飞的接口);

4. 如何解决

继承或依赖(推荐)

5. 关键代码

  • 适配器继承或依赖已有的对象,实现想要的目标接口

6. 应用实例

  • 美国电器110V,中国220V,就要有一个适配器将110V转化为220V;
  • JAVAJDK1.1提供了Enumeration接口,而在1.2中提供了Iterator接口,想要使用1.2的JDK,则要将以前系统的Enumeration接口转化为Iterator接口,这时就需要适配器模式;
  • 在LINUX上运行WINDOWS程序;
  • JAVA中的jdbc;

7. 优点

  • 可以让任何两个没有关联的类一起运行;
  • 提高了类的复用;
  • 增加了类的透明度;
  • 灵活性好;

8. 缺点

  • 过多地使用适配器,会让系统非常零乱,不易整体进行把握;
    比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现,一个系统如果太多出现这种情况,无异于一场灾难 因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构

  • 由于JAVA至多继承一个类,所以至多只能适配一个适配者类,而且目标类必须是抽象类;

9. 使用场景

  • 有动机地修改一个正常运行的系统的接口,这时应该考虑使用适配器模式。

10. 注意事项

  • 适配器不是在详细设计时添加的,而是解决正在服役的项目的问题

实现

在这里插入图片描述

  1. MediaPlayer接口和一个实现了MediaPlayer接口的实体类AudioPlayer默认情况下,AudioPlayer可以播放mp3格式的音频文件;
  2. 接口AdvancedMediaPlayer和实现了AdvancedMediaPlayer接口的实体类该类可以播放vlc和mp4格式的文件;
  3. AudioPlayer播放其他格式的音频文件为了实现这个功能,我们需要创建一个实现了MediaPlayer接口的适配器类MediaAdapter,并使用AdvancedMediaPlayer对象来播放所需的格式;
  4. AudioPlayer使用适配器类MediaAdapter传递所需的音频类型,不需要知道能播放所需格式音频的实际类;
  5. AdapterPatternDemo使用AudioPlayer类来播放各种格式;

范例

1. 为媒体播放器和更高级的媒体播放器创建接口.

MediaPlayer.java

package com.demo.gof;
public interface MediaPlayer {public void play(String audioType, String fileName);
}

AdvancedMediaPlayer.java

package com.demo.gof;
public interface AdvancedMediaPlayer {  public void playVlc(String fileName);public void playMp4(String fileName);
}

2. 创建实现了 AdvancedMediaPlayer 接口的实体类

VlcPlayer.java

package com.demo.gof;
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

package com.demo.gof;
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

package com.demo.gof;
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

package com.demo.gof;
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

package com.demo.gof;
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");}
}

编译运行以上 Java 范例,输出结果如下

$ javac -d . src/main/com.demo/gof/AdapterPatternDemo.java
$ java  com.demo.gof.AdapterPatternDemo
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

相关文章:

06-Java适配器模式 ( Adapter Pattern )

原型模式 摘要实现范例 适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁 适配器模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能 举个真实的例子,读卡器是作为内存卡和笔记本之间的适配器。您将内…...

C# CAD交互界面-自定义面板集-添加快捷命令(五)

运行环境 vs2022 c# cad2016 调试成功 一、引用 using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.Runtime; using Autodesk.AutoCAD.Windows; using System; using System.Drawing; using System.Windows.Forms; 二、代码说明 [CommandMethod("Cre…...

Spring boot集成各种数据源操作数据库

一、最基础的数据源方式 1.导入maven依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency <dependency><groupId>com.mysql</groupId><art…...

K8s环境下rook-v1.13.3部署Ceph-v18.2.1集群

文章目录 1.K8s环境搭建2.Ceph集群部署2.1 部署Rook Operator2.2 镜像准备2.3 配置节点角色2.4 部署operator2.5 部署Ceph集群2.6 强制删除命名空间2.7 验证集群 3.Ceph界面 1.K8s环境搭建 参考&#xff1a;CentOS7搭建k8s-v1.28.6集群详情&#xff0c;把K8s集群完成搭建&…...

【JavaEE】传输层网络协议

传输层网络协议 1. UDP协议 1.1 特点 面向数据报&#xff08;DatagramSocket&#xff09;数据报大小限制为64k全双工不可靠传输有接收缓冲区&#xff0c;无发送缓冲区 UDP的特点&#xff0c;我理解起来就是工人组成的**“人工传送带”**&#xff1a; 面向数据报&#xff08;…...

08-Java过滤器模式 ( Filter Pattern )

Java过滤器模式 实现范例 过滤器模式&#xff08;Filter Pattern&#xff09;或允许开发人员使用不同的标准来过滤一组对象&#xff0c;通过逻辑运算以解耦的方式把它们连接起来 过滤器模式&#xff08;Filter Pattern&#xff09; 又称 标准模式&#xff08;Criteria Pattern…...

ChatGPT高效提问—prompt常见用法(续篇八)

ChatGPT高效提问—prompt常见用法(续篇八) 1.1 对抗 ​ 对抗是一个重要主题,深入探讨了大型语言模型(LLM)的安全风险。它不仅反映了人们对LLM可能出现的风险和安全问题的理解,而且能够帮助我们识别这些潜在的风险,并通过切实可行的技术手段来规避。 ​ 截至目前,网络…...

微软.NET6开发的C#特性——接口和属性

我是荔园微风&#xff0c;作为一名在IT界整整25年的老兵&#xff0c;看到不少初学者在学习编程语言的过程中如此的痛苦&#xff0c;我决定做点什么&#xff0c;下面我就重点讲讲微软.NET6开发人员需要知道的C#特性&#xff0c;然后比较其他各种语言进行认识。 C#经历了多年发展…...

容器基础知识:容器和虚拟化的区别

虚拟化与容器化对比 容器化和虚拟化都是用于优化资源利用率并实现高效应用程序部署的技术。然而&#xff0c;它们在方法和关键特征上存在差异&#xff1a; 虚拟化: 可以理解为创建虚拟机 (VM)。虚拟机模拟一台拥有自己硬件&#xff08;CPU、内存、存储&#xff09;和操作系统…...

【Linux】vim的基本操作与配置(下)

Hello everybody!今天我们继续讲解vim的操作与配置&#xff0c;希望大家在看过这篇文章与上篇文章后都能够轻松上手vim! 1.补充 在上一篇文章中我们说过了&#xff0c;在底行模式下set nu可以显示行号。今天补充一条&#xff1a;set nonu可以取消行号。这两条命令大家看看就可…...

[office] 图文演示excel怎样给单元格添加下拉列表 #知识分享#经验分享

图文演示excel怎样给单元格添加下拉列表 在Excel表格中输入数据的时候&#xff0c;为了简便快捷的输入&#xff0c;经常需要给Excel单元格添加一个下拉菜单&#xff0c;这样在输入数据时不必按键盘&#xff0c;只是用鼠标选择选项就可以了。 比的位置。 4、可以看到一个预览的…...

【RT-DETR有效改进】利用SENetV2重构化网络结构 (ILSVRC冠军得主,全网独家首发)

👑欢迎大家订阅本专栏,一起学习RT-DETR👑 一、本文介绍 本文给大家带来的改进机制是SENetV2,其是2023.11月的最新机制(所以大家想要发论文的可以在上面下点功夫),其是一种通过调整卷积网络中的通道关系来提升性能的网络结构。SENet并不是一个独立的网络模型,而…...

【Linux】学习-进程间通信

进程间通信 介绍 进程间通信的本质 进程间通信的前提&#xff0c;首先需要让不同的进程看到同一块“内存”此“内存”一定不属于任何进程&#xff0c;而应该强调共享二字 进程间通信的目的 数据传输&#xff1a;一个进程需要将它的数据发送给另一个进程 资源共享&#xff1a;…...

45. C++ 字符指针和字符串

一、字符指针可以指向一个字符串。 我们可以用字符串常量对字符指针进行初始化。例如&#xff0c;有说明语句&#xff1a; char *str "This is a string.";是对字符指针进行初始化。此时&#xff0c;字符指针指向的是一个字符串常量的首地址&#xff0c;即指向字符…...

如何制作一款3D FPS游戏

制作一款3D FPS游戏是一个复杂的过程&#xff0c;需要涵盖多个方面&#xff0c;包括游戏设计、游戏引擎选择、模型制作、音效制作、关卡设计等。下面是一个关于如何制作一款3D FPS游戏的超长文章。 游戏设计 首先&#xff0c;你需要确定游戏的整体设计和核心玩法。这包括游戏的…...

人工智能|深度学习——使用多层级注意力机制和keras实现问题分类

代码下载 使用多层级注意力机制和keras实现问题分类资源-CSDN文库 1 准备工作 1.1 什么是词向量? ”词向量”&#xff08;词嵌入&#xff09;是将一类将词的语义映射到向量空间中去的自然语言处理技术。即将一个词用特定的向量来表示&#xff0c;向量之间的距离&#xff08;例…...

C语言常见面试题:C语言中如何进行网页开发编程?

在C语言中进行网页开发通常不是一个直接的过程&#xff0c;因为C语言主要用于系统级编程&#xff0c;而不是Web开发。传统的Web开发主要使用高级语言如JavaScript、Python、Ruby、PHP等&#xff0c;以及与Web相关的技术&#xff0c;如HTML、CSS和数据库。 然而&#xff0c;如果…...

DevOps落地笔记-20|软件质量:决定系统成功的关键

上一课时介绍通过提高工程效率来提高价值交付效率&#xff0c;从而提高企业对市场的响应速度。在提高响应速度的同时&#xff0c;也不能降低软件的质量&#xff0c;这就是所谓的“保质保量”。具备高质量软件&#xff0c;高效率的企业走得更快更远。相反&#xff0c;低劣的软件…...

政安晨:梯度与导数~示例演绎《机器学习·神经网络》的高阶理解

这篇文章确实需要一定的数学基础&#xff0c;第一次接触的小伙伴可以先看一下我示例演绎这个主题的前两篇文章&#xff1a; 示例演绎机器学习中&#xff08;深度学习&#xff09;神经网络的数学基础——快速理解核心概念&#xff08;一&#xff09;&#xff1a; 政安晨&#…...

CTFSHOW命令执行web入门29-54

description: >- 这里就记录一下ctfshow的刷题记录是web入门的命令执行专题里面的题目,他是有分类,并且覆盖也很广泛,所以就通过刷这个来,不过里面有一些脚本的题目发现我自己根本不会笑死。 如果还不怎么知道写题的话,可以去看我的gitbook,当然csdn我也转载了我自己的…...

python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)

更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...

Java入门学习详细版(一)

大家好&#xff0c;Java 学习是一个系统学习的过程&#xff0c;核心原则就是“理论 实践 坚持”&#xff0c;并且需循序渐进&#xff0c;不可过于着急&#xff0c;本篇文章推出的这份详细入门学习资料将带大家从零基础开始&#xff0c;逐步掌握 Java 的核心概念和编程技能。 …...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的

修改bug思路&#xff1a; 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑&#xff1a;async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...

MFC 抛体运动模拟:常见问题解决与界面美化

在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...

从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障

关键领域软件测试的"安全密码"&#xff1a;Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力&#xff0c;从金融交易到交通管控&#xff0c;这些关乎国计民生的关键领域…...

windows系统MySQL安装文档

概览&#xff1a;本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容&#xff0c;为学习者提供全面的操作指导。关键要点包括&#xff1a; 解压 &#xff1a;下载完成后解压压缩包&#xff0c;得到MySQL 8.…...

数学建模-滑翔伞伞翼面积的设计,运动状态计算和优化 !

我们考虑滑翔伞的伞翼面积设计问题以及运动状态描述。滑翔伞的性能主要取决于伞翼面积、气动特性以及飞行员的重量。我们的目标是建立数学模型来描述滑翔伞的运动状态,并优化伞翼面积的设计。 一、问题分析 滑翔伞在飞行过程中受到重力、升力和阻力的作用。升力和阻力与伞翼面…...

HTML前端开发:JavaScript 获取元素方法详解

作为前端开发者&#xff0c;高效获取 DOM 元素是必备技能。以下是 JS 中核心的获取元素方法&#xff0c;分为两大系列&#xff1a; 一、getElementBy... 系列 传统方法&#xff0c;直接通过 DOM 接口访问&#xff0c;返回动态集合&#xff08;元素变化会实时更新&#xff09;。…...

聚六亚甲基单胍盐酸盐市场深度解析:现状、挑战与机遇

根据 QYResearch 发布的市场报告显示&#xff0c;全球市场规模预计在 2031 年达到 9848 万美元&#xff0c;2025 - 2031 年期间年复合增长率&#xff08;CAGR&#xff09;为 3.7%。在竞争格局上&#xff0c;市场集中度较高&#xff0c;2024 年全球前十强厂商占据约 74.0% 的市场…...

Linux-进程间的通信

1、IPC&#xff1a; Inter Process Communication&#xff08;进程间通信&#xff09;&#xff1a; 由于每个进程在操作系统中有独立的地址空间&#xff0c;它们不能像线程那样直接访问彼此的内存&#xff0c;所以必须通过某种方式进行通信。 常见的 IPC 方式包括&#…...