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{

    @Override
    public void playVlc(String fileName) {
        System.out.println("播放 VLC 文件。名称: " + fileName);
    }

    @Override
    public void playMp4(String fileName) {
        // 无操作
    }

}
public class Mp4Player implements AdvancedMediaPlayer {

    @Override
    public void playVlc(String fileName) {
        // 无操作
    }

    @Override
    public 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();
        }
    }

    @Override
    public 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;

    @Override
    public 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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

golang WaitGroup的使用与底层实现

使用的go版本为 go1.21.2 首先我们写一个简单的WaitGroup的使用代码 package mainimport ("fmt""sync" )func main() {var wg sync.WaitGroupwg.Add(1)go func() {defer wg.Done()fmt.Println("xiaochuan")}()wg.Wait() }WaitGroup的基本使用场…

AI 文本转视频(视频生产工具分享)

AI 文本转视频(视频生产工具分享) 介绍 ​ 想要根据任何描述轻松创建有趣的视频吗?然后,您应该尝试使用人工智能视频生成工具。毫无疑问,人工智能是未来。人工智能视频生成器可以轻松地从任何文本制作视频。只需几分…

(一)Tiki-taka算法(TTA)求解无人机三维路径规划研究(MATLAB)

一、无人机模型简介: 单个无人机三维路径规划问题及其建模_IT猿手的博客-CSDN博客 参考文献: [1]胡观凯,钟建华,李永正,黎万洪.基于IPSO-GA算法的无人机三维路径规划[J].现代电子技术,2023,46(07):115-120 二、Tiki-taka算法(TTA&#xf…

为何要隐藏IP地址?代理ip在网络安全和隐私保护中的作用是什么?

目录 前言 一、为何要隐藏IP地址? 1. 保护隐私。 2. 防止网络攻击。 3. 避免限制和审查。 二、网络上哪些行为需要隐藏IP和更换IP? 1. 下载种子文件。 2. 访问受限网站。 3. 保护网络隐私。 4. 避免被封禁。 三、代理IP在网络安全和隐私保护中…

数据结构-04-队列

1-队列的结构和特点 生活中我们排队买票,先来的先买,后来的人只能站末尾,不允许插队。先进者先出,这就是典型的"队列"。队列跟栈非常相似,支持的操作也很有限,最基本的操作也是两个:入…

Paraformer 语音识别原理

Paraformer(Parallel Transformer)非自回归端到端语音系统需要解决两个问题: 准确预测输出序列长度,送入预测语音信号判断包含多少文字。 如何从encoder 的输出中提取隐层表征,作为decoder的输入。 采用一个预测器(Predictor&…

windows配置go调用python的编译环境

go是支持调用python代码的,之前写了几篇linux的部署教程,因为觉得windows的不复杂就没有写,结果今天新部署一个Windows的环境,有些步骤想不起来了,好记性不如烂笔头,还是记录一下吧。 这些是之前写的linux…

Vue3Element-plus编写一个简版的字典服务

之前公司有维护过一个内部的字典平台,基本步骤和页面如下 添加字典属性弹窗 添加枚举值弹窗 基本业务代码如下 核心代码 import { defineStore } from pinia export const useDictionary defineStore(dictionary, {state: () > ({dict: [],dictObj: {},}),actions: {s…

C语言-指针讲解(4)

在上一篇博客中: C语言-指针讲解(3) 我们给大家介绍了指针进阶的用法 让下面我们来回顾一下讲了什么吧: 1.字符指针变量类型以及用法 2.数组指针本质上是一个指针,里面存放数组的地址。而指针数组本质上是个数组,里面存放的是指针…

知识图谱最简单的demo实现

一、简介 知识图谱整个建立过程可以分为以下几点: #mermaid-svg-zJuLB8k8EgBQF8M0 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-zJuLB8k8EgBQF8M0 .error-icon{fill:#552222;}#mermaid-svg-zJuLB8k8E…

图片点击放大

在列表中添加插槽 <template slot-scope"scope">&#xff0c;获取当前点击的数据 在图片中添加点击事件的方法&#xff0c;用来弹出窗口 <vxe-columnfield"icon"title"等级图标"><template slot-scope"scope"><…

Kubernetes(K8s) Pod详解-05

Pod详解 Pod介绍 Pod结构 每个Pod中都可以包含一个或者多个容器&#xff0c;这些容器可以分为两类&#xff1a; 用户程序所在的容器&#xff0c;数量可多可少 Pause容器&#xff0c;这是每个Pod都会有的一个根容器&#xff0c;它的作用有两个&#xff1a; 可以以它为依据…

hadoop完全分布式搭建

文章目录 集群部署规划服务器准备Mobaxterm 远程登录实验前准备安装软件工具关闭防火墙 安装 JDK 和 Hadoop创建软件包目录解压软件包配置环境变量 集群搭建先创建 HDFS 工作目录和 LOG 目录配置集群配置环境配置 HDFS 主节点信息、持久化和数据文件的主目录配置 HDFS 默认的数…

程序员养生之道:延寿不忘初心——延寿必备

文章目录 每日一句正能量前言如何养生饮食篇运动篇休息篇后记 每日一句正能量 现代社会已不是大鱼吃小鱼的年代&#xff0c;而是快鱼吃慢鱼的年代。 前言 在IT行业中&#xff0c;程序员是一个重要的职业群体。由于长时间的繁重编程工作&#xff0c;程序员们常常忽略了身体健康…

Unity中Shader编译目标渲染器

文章目录 前言一、Unity在打包时&#xff0c;会把Shader编译成不同平台对应的代码我们在状态栏&#xff0c;可以看见我们目前所处于的目标平台 二、在Unity中&#xff0c;怎么指定目标平台1、#pragma only_renderers2、#pragma exclude_renderers 三、我们测试一下看看效果1、 …

postman利用pre-request script自动设置token

场景&#xff1a; 我们请求接口&#xff1a;/api/rest/user/list获取用户列表&#xff0c;但是该接口需要在header中带上Authorization表示的鉴权Token才行。 而登录接口/api/rest/login&#xff0c;则可以返回改Token 常规方案 我们先调登录接口/api/rest/login获取到Toke…

极简云网络验证系统开源源码

极简云验证&#xff0c;多样化应用管理方式&#xff0c;多种项目任你开发&#xff0c;分布式应用开关&#xff0c;让您的应用开发更简单&#xff0c;完美实现多用户多应用管理。 支持多应用卡密生成&#xff1a; 卡密生成 单码卡密 次数卡密 会员卡密 积分卡密 卡密管理 卡密长…

了解http协议

http的相关概念 互联网&#xff1a;是网络的网络&#xff0c;是所有类型网络的母集 因特网&#xff1a;世界上最大的互联网网络。即因特网概念从属于互联网概念。习惯上&#xff0c;大家把连接在因特网上的计算机都成为主机。 万维网&#xff1a;数据库 URL&#xff1a;万维…

亚马逊云科技向量数据库与生成式AI的完美融合:落地实践详解(四)

以往 OpenSearch 摄入时的一些最佳实践中并不包含 knn 的情况&#xff0c;所以在 knn 索引存在的情况&#xff0c;不能完全参照之前的结论&#xff0c;通过以上三种不同的实验方式&#xff0c;在多次实验的过程中&#xff0c;本文得到了以下的一些实践经验和结论&#xff0c;供…

自研分布式IM-HubuIM RFC草案

HubuIM RFC草案 消息协议设计 基本协议 评估标准 【性能】协议传输效率&#xff0c;尽可能降低端到端的延迟&#xff0c;延迟高于200ms用户侧就会有所感知 【兼容】既要向前兼容也要向后兼容 【存储】减少消息包的大小&#xff0c;降低空间占用率&#xff0c;一个字节在亿…