java设计模式学习之【适配器模式】

news2025/1/12 8:42:23

文章目录

  • 引言
  • 适配器模式简介
    • 定义与用途:
    • 实现方式:
      • 类型
  • 使用场景
  • 优势与劣势
  • 适配器模式在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

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

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

相关文章

SSM众筹管理系统开发mysql数据库web结构java编程计算机网页源码eclipse项目

一、源码特点 SSM 众筹管理系统是一套完善的信息系统,结合springMVC框架完成本系统,对理解JSP java编程开发语言有帮助系统采用SSM框架(MVC模式开发),系统具有完整的源代码和数据库,系统主要采用B/S模式开…

map()的用法

JavaScript Array map() 方法 先说说这个方法浏览器的支持: 支持五大主流的浏览器, 特别注意:IE 9 以下的浏览器不支持,只支持IE 9以上的版本的浏览器 特别注意:IE 9 以下的浏览器不支持,只支持IE 9以上的…

设计师必看!揭秘顶级外卖平台APP背后的设计原则

在数字化和移动互联网盛行的今天,外卖平台APP已经成为我们生活中的重要组成部分。作为设计师,你是否也曾思考过如何通过设计优化用户体验,提升品牌形象,甚至直接推动业务增长?今天,我们将向你揭示顶级外卖平…

Python内置类属性__cmp__属性的使用教程

概要 Python是一种简单而强大的编程语言,它提供了许多内置的类和功能,以帮助开发人员更轻松地实现各种任务。其中一个内置类属性是__cmp__,它允许我们在自定义类中实现对象之间的比较操作。本文将详细介绍__cmp__属性的使用方法,…

DistilBERT模型训练实战

LLM似乎正在接管世界,但许多人仍然不真正理解他们是如何运作的。 我从事机器学习工作已有几年,并且对自然语言处理和最近的进展非常着迷。 尽管我阅读了大部分随附的论文,但训练这些模型对我来说仍然是一个谜,这就是为什么我决定…

CSS中的非布局样式+CSS布局 前端开发入门笔记(十一)

CSS中的非布局样式 在CSS中,非布局样式是指那些不会直接影响页面布局的样式。这些样式主要关注的是元素的颜色、字体、背景、边框、阴影等视觉效果。以下是一些常见的非布局CSS样式: 文本样式:包括字体(font-family)…

以太网PHY,MAC接口

本文主要介绍以太网的 MAC 和 PHY,以及之间的 MII(Media Independent Interface ,媒体独立接口)和 MII 的各种衍生版本——GMII、SGMII、RMII、RGMII等。 简介 从硬件的角度看,以太网接口电路主要由MAC(M…

GAN:WGAN-GP-带有梯度惩罚的WGAN

论文:https://arxiv.org/pdf/1704.00028.pdf 代码:GitHub - igul222/improved_wgan_training: Code for reproducing experiments in "Improved Training of Wasserstein GANs" 发表:2017 WGAN三部曲的终章-WGAN-GP 摘要 WGAN在…

YOLOv5全网独家首发改进:SENetv2,Squeeze-Excitation模块融合Dense Layer,效果秒杀SENet

💡💡💡本文自研创新改进:SENet v2,针对SENet主要优化点,提出新颖的多分支Dense Layer,并与Squeeze-Excitation网络模块高效融合,融合增强了网络捕获通道模式和全局知识的能力 推荐指数:五星 收录 YOLOv5原创自研 https://blog.csdn.net/m0_63774211/catego…

GPT市场将取代插件商店 openAI已经关闭plugins申请,全部集成到GPTs(Actions)来连接现实世界,可以与物理世界互动了。

Actions使用了plugins的许多核心思想,也增加了新的特性。 ChatGPT的"Actions"与"Plugins"是OpenAI在GPT模型中引入的两种不同的功能扩展机制。这两种机制的目的是增强模型的功能,使其能够处理更多样化的任务和请求。下面是对两者的比…

应用于智慧工厂的AI边缘计算盒子+AI算法软硬一体化方案

智慧工厂解决方案,传统工厂/生产管理,普遍存在运营粗放、效率低、应变能力差、安全隐患突出、资源不平衡等“行业症状”; 以英码产品为核心的智能化场景解决方案,可以从本质上根治这些“症状”,如企业可利用智能预测系…

RocketMQ Copilot 一款面向 Apache RocketMQ 的智能辅助运维系统

一、RocketMQ简介 ocketMQ是阿里巴巴研发的一款分布式消息中间件,后开源给Apache基金会,成为apache的顶级开源项目。它具有高性能、高可靠、高实时和分布式的特点。RocketMQ主要应用于解决应用耦合,消息分发,流量削锋等问题。 R…

七年 4 个阶段:滴滴可观测架构演进与实践

一分钟精华速览 在当前阶段,可观测性的建设并没有统一的执行路径。每家公司会根据自身的业务需求、运营模式和规模,形成一套独特的实践方案。为了应对业务规模的扩大和需求的变化,可观测团队必须持续优化和升级其架构,并始终保证…

2023年中国金融科技研究报告

第一章 行业概况 1.1 定义 金融科技(FinTech, Financial Technology)代表了金融和技术的交汇。这一领域虽然处于发展的初期阶段,但已经展现出深远的影响力。金融科技的业务模式多样,涵盖了从传统金融服务的数字化转型到新兴技术…

亚马逊云与生成式 AI 的融合——生成式AI的应用领域

文章目录 前言亚马逊云科技增强客户体验聊天机器人和虚拟助手亚马逊云科技 鸿翼:提供精准检索和问答,显著提升全球化售后服务体验AI 赋能的联络中心智能导购&个性化推荐智慧数字人 提升员工生成力和创造力对话式搜索亚马逊云科技 西门子&#xff1…

mongoDB非关系型数据库学习记录

一、简介 1.1Mongodb是什么 MongoDB是一个基于分布式文件存储的数据库,官方地址https://www.mongodb.com/ 1.2数据库是什么 数据库(DataBase)是按照数据结构来组织、存储和管理数据的应用程序 1.3数据库的作用 数据库的主要作用就是管理数据,对数据进行增©、删(d)、…

Node-red

Node-Red 什么是Node-redNode-red的特点 Node-red的Windows安装安装Node.js安装包下载安装包安装安装检查 安装Node-red安装Note-red运行Note-red 什么是Node-red Node-RED 是一种编程工具,用于以新颖有趣的方式将硬件设备、API 和在线服务连接在一起。 Node-RED 是…

【【Micro Blaze按键中断实验】】

Micro Blaze按键中断实验 中断是一种当满足要求的突发事件发生时通知处理器进行处理的信号。中断可以由硬件处理单元和外 部设备产生,也可以由软件本身产生。对硬件来说,中断信号是一个由某个处理单元产生的异步信号,用 来引起处理器的注意。…

如何利用 Snapchat 制定数字营销战略

近年来,Snapchat已成为数字营销领域的重要参与者。Snapchat 已经发展成为一种复杂的营销工具,被各种公司用来与年轻受众互动,此前它最初被认为是一个专门供青少年发布快速、转瞬即逝内容的平台。Snapchat 上的日活跃用户数量超过 2.8 亿&…

CMD命令切换至D盘

1.使用快捷键winr进入如下所示界面: 2.在框内输入CMD 后点击确定,即可进入如下界面; 3.输入d: 后按下enter即可转换成功; 补充一些CMD命令: 1. appwiz.cpl:程序和功能 2. calc:启动计算器 3.…