【设计模式】适配器模式

news2024/11/27 4:24:17

适配器模式属于结构型模式,主要解决两个已存在的功能相近的接口间不能兼容的问题。在准备将一个接口对接到另一个接口中时,发现另一个接口(目标)与准备对接的接口(适配者)因不兼容而无法正常运行功能时,就可以使用适配器模式来增加一个适配器对接二者。不要说二者谁是主谁是客,只有适配者通过适配器适配目标。当我想把一个功能模块加到另一个模块中时,要加的这个模块就是适配者。

文章目录

  • 适配器模式的介绍
    • 优点
    • 缺点
    • 应用场景
  • 适配器的使用
    • 使用对象适配器方式
      • 类图
      • 原有的架构
      • 使用适配器接入视频模块
        • 第一步,创建视频媒体接口
        • 第二步,创建MP4播放器和WMV播放器
        • 第三步,创建视频适配器
        • 第四步,编写测试类测试
    • 使用类适配器方式
      • 类图
      • 原有的架构
      • 使用适配器接入视频模块
        • 第一步,创建MP4适配器
        • 第二步,创建WMV适配器
        • 第三步,在测试类中测试

适配器模式的介绍

适配器模式通过实现目标接口,同时继承或关联适配者接口来完成功能的适配,让两个不相关的接口能够共同工作。

优点

  • 灵活性高,符合开闭原则
  • 提高了类的复用性(本来因为接口不兼容而无法使用之前的功能,只能重新添加功能,但现在可以通过适配器调用之前的功能了)

缺点

  • 过多使用适配器会导致项目的结构混乱

应用场景

  • 适配器其实是在现有设计存在缺陷时作为一种“补偿模式”使用,如果设计之初能够规避接口不兼容的问题,那就没必要使用适配器。但人与人之间存在差异,那不兼容问题就无可避免,比如各国的电压不同,插座的设计也不同,这就必须使用适配器。

  • Java与数据库连接的驱动工具JDBC也是一个适配器,Java提供一个抽象接口,由不同的数据库厂商在数据库引擎接口与JDBC接口间实现一个适配器(JDBC驱动),以此达到Java能够连接不同数据库的功能。

  • 当需要对接第三方提供给我的接口时,发现该接口的定义与我实现的功能接口存在差异时需要使用适配器模式。

  • 当开发新系统时,发现之前系统的功能模块可以复用但又于当前系统接口不兼容时可以使用适配器模式。

适配器的使用

当前系统存在一个媒体播放器,但是编写播放器时只考虑到了播放音频,所以只存在一个MP3播放器和音频媒体的接口。但现在我想让播放器可以播放视频,并已经编写了一组视频媒体的播放器。可准备对接媒体播放器时发现它只支持音频媒体,于是我决定使用适配器解决兼容问题。

适配器有两种实现方式,分别为类适配器和对象适配器。类适配器使用的是继承关系来实现,对象适配使用的是关联关系来实现。



使用对象适配器方式

对象适配器实现了目标接口(音频媒体),同时内部持有适配者接口(视频媒体)的实例,然后再按照目标的接口的方法去转换适配者实现类。

类图

image-20221122213948231


原有的架构

音频媒体

package 设计模式.结构型模式.适配器模式;

public interface 音频媒体 {
    String 播放音乐(String 名称);
}

MP3播放器

package 设计模式.结构型模式.适配器模式;

public class MP3播放器 implements 音频媒体 {

    @Override
    public String 播放音乐(String 名称) {
        return "准备播放MP3格式的音乐:" + 名称;
    }
}

媒体播放器

package 设计模式.结构型模式.适配器模式;

public class 媒体播放器 {

    public void 播放(音频媒体 音乐, String 名称){
        System.out.println(音乐.播放音乐(名称));
    }
}

测试类

package 设计模式.结构型模式.适配器模式;

public class 测试类 {
    public static void main(String[] args) {
        媒体播放器 播放器 = new 媒体播放器();
        MP3播放器 mp3 = new MP3播放器();
        播放器.播放(mp3, "小苹果.mp3");
    }
}

测试效果

image-20221122214400042


使用适配器接入视频模块

以下的步骤都是在音频播放器原有的架构上搭建,不会影响到之前的类。

第一步,创建视频媒体接口

视频媒体

package 设计模式.结构型模式.适配器模式;

public interface 视频媒体 {
    String 播放视频(String 名称);
}

第二步,创建MP4播放器和WMV播放器

MP4播放器

package 设计模式.结构型模式.适配器模式;

public class MP4播放器 implements 视频媒体 {
    @Override
    public String 播放视频(String 名称) {
        return "现在开始播放MP4格式的视频:"+名称;
    }
}

WMV播放器

package 设计模式.结构型模式.适配器模式;

public class WMV播放器 implements 视频媒体 {
    @Override
    public String 播放视频(String 名称) {
        return "现在开始播放WMV格式的视频:"+名称;
    }
}

第三步,创建视频适配器

视频适配器

package 设计模式.结构型模式.适配器模式;

public class 视频适配器 implements 音频媒体 {

    视频媒体 视频;

    视频适配器(视频媒体 视频){
        this.视频 = 视频;
    }

    @Override
    public String 播放音乐(String 名称) {
        // 实现音频媒体的接口,与视频媒体进行对接
        return 视频.播放视频(名称);
    }
}

第四步,编写测试类测试

测试类

package 设计模式.结构型模式.适配器模式;

public class 测试类 {
    public static void main(String[] args) {
        媒体播放器 播放器 = new 媒体播放器();
        MP3播放器 mp3 = new MP3播放器();
        播放器.播放(mp3, "小苹果.mp3");
        视频适配器 适配器 = new 视频适配器(new MP4播放器());
        播放器.播放(适配器, "勇敢的心.mp4");
        播放器.播放(new 视频适配器(new WMV播放器()), "疯狂动物城.wmv");
    }
}

测试结果

在这里插入图片描述





使用类适配器方式

使用类适配器时,适配器实现目标接口方法,同时继承适配者实现类,而我创建了两个视频播放器,那就需要创建两个适配器来转换。

类图

image-20221122220439275

原有的架构

和对象适配器中的原有架构相同

使用适配器接入视频模块

以下的步骤都是在音频播放器原有的架构上搭建,并且省略了视频媒体接口和媒体播放器的创建,因为结构与上方的一样。

第一步,创建MP4适配器

MP4适配器

package 设计模式.结构型模式.适配器模式;

public class MP4适配器 extends MP4播放器 implements 音频媒体 {

    @Override
    public String 播放音乐(String 名称) {
        return 播放视频(名称);
    }
}

第二步,创建WMV适配器

WMV适配器

package 设计模式.结构型模式.适配器模式;

public class WMV适配器 extends WMV播放器 implements 音频媒体 {

    @Override
    public String 播放音乐(String 名称) {
        return 播放视频(名称);
    }
}

第三步,在测试类中测试

测试类

package 设计模式.结构型模式.适配器模式;

public class 测试类 {
    public static void main(String[] args) {
        媒体播放器 播放器 = new 媒体播放器();
        MP3播放器 mp3 = new MP3播放器();
        播放器.播放(mp3, "小苹果.mp3");
        播放器.播放(new MP4适配器(), "勇敢的心.mp4");
        播放器.播放(new WMV适配器(), "疯狂动物城.wmv");
    }
}

测试结果

image-20221122221112862

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

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

相关文章

Allegro如何打盲埋孔操作指导

Allegro如何打盲埋孔操作指导 Allegro支持打盲埋孔,具操作如下 首先保证库路径下方有盲埋孔的封装 打开规则管理器 选择Physical规则,点击VIAS,会出现一个对话框,勾选show vias from Library ,出现孔的封装 把孔添加到via list里面去,之后点击ok 加好的效果如

web前端-javascript-数据类型(6种数据类型/字符串、数值、布尔值、空值、未定义、对象,String字符串、引号问题、转义字符、字面量和变量输出)

文章目录数据类型1. 介绍说明2. String 字符串引号问题转义字符字面量和变量的输出数据类型 var str "hello"; str 我说:"今天天气真不错!";str 我说:"今天\t天气真不错!"; str "\\\\\\";//输出字面量str …

ESP32基础应用之使用两个ESP32通过阿里云物联网平台实现相互通信

文章目录1 阿里云物联网平台2 程序编写2.1 ESP32-COM4 设备2.1 ESP32-COM5 设备3 实验现象分析1 阿里云物联网平台 在设备管理下创建两个设备,参考ESP32基础应用之ESP32与阿里云物联网平台实现数据互传(MQTT协议) 在规则引擎下创建云产品流…

前后端分离 基础(新增与查询)

目录 一,后端 1.1 修改settings---->搜索Maven 1.2 application.yml文件与jdbc.properties文件 对应数据库的账号密码 application.yml 1.4 jdbc.properties 1.3 generatorConfig.xml jdbc驱动jar包 1.4 从本地导入pom依赖 POM 1.5 自动生成 1.6 各个层…

axure学习:设置部件固定到浏览器,预览时部件消失

​在Axure中有一个非常好用且常用的部件——动态面板,动态面板很常用的一个功能是利用不同状态页做tab的切换、轮播图等,但咱们今天要说的不是关于这方面的问题。这里我们要说的是关于动态面板的属性:固定到浏览器的使用。 关于这一点&#…

react(任意组件之间传值--消息订阅与发布、路由)

目录 兄弟组件传值--任意组件之间传值 fetch发送请求: react 路由 解决样式丢失的问题: 路由的模糊匹配和严格匹配 嵌套路由 向路由组件传参 前端中文学习网站:印记中文 - 深入挖掘国外前端新领域,为国内 Web 前端开发人员提…

最优化方法总结——梯度下降法、最速下降法、牛顿法、高斯牛顿法、LM法、拟牛顿法

目录 1 最优化方法的结构 2 常用最优化方法对比分析 3 相关计算公式 1 最优化方法的结构 最优化问题的一般形式为: 其中为决策变量,是目标函数,为约束集或可行域。特别地,如果,则最优化问题成为无约束最优化问题。 …

目标检测DiffusionDet: Diffusion Model for Object Detection

先贴一张流程图: github:GitHub - ShoufaChen/DiffusionDet: PyTorch implementation of DiffusionDet (https://arxiv.org/abs/2211.09788) pdf: https://arxiv.org/abs/2211.09788 Abstract: 本文提出了一个新的框架DiffusionDet,将目标检测问题构建…

Lombok的@Data注解包含的方法(没有全参构造方法)

Lombok的Data注解包含的方法(没有全参构造方法) 目录Lombok的Data注解包含的方法(没有全参构造方法)结论:测试:1.Maven引入依赖2.安装lombok插件3.编写实体类4.编译5.查看target文件6.编译后的源代码结论&a…

实用的3款视频添加水印软件分享,简单易上手

如今刷短视频已经成为许多小伙伴饭后闲暇之余消遣的项目,也有不少人因此加入了创作短视频的队列。但是在分享前,最好是对自己的作品加上水印。为什么呢?第一是可以起到更好的宣传作用,第二是防止他人盗窃作品内容,毕竟…

卷积输入输出维度计算公式,Conv, Dilation Conv, Padding, Kernel_size, Output的维度计算关系

define i input o output p padding k kernel_size s stride d dilation 公式 o [i 2p - k - (k-1)(d-1)]/s 1 举例 当 padding “same” 时,输入尺度和输出尺度相同。 oi 则有: p[(i-1)s-i k(k-1)(d-1)]*0.5 假设 k5, s1, 那么 p[(i-1) …

深度学习入门---《白话机器学习的数学》笔记

文章目录一、基础:回归的实现1、训练数据click.csv2、参考公式:3、代码实现:4、运行结果:5、验证:二、多项式回归1、参考公式2、代码实现3、运行结果三、随机梯度下降法的实现1、参考公式小批量(mini-batch…

F. Quests(二分)

Problem - F - Codeforces 有n个任务。如果你完成第i个任务,你将获得ai币。你每天最多只能完成一个任务。然而,一旦你完成了一个任务,在K天内你不能再做同样的任务。(例如,如果k2,你在第1天做了任务1,那么你…

radiantq:jQuery Gantt Package--好使的HTML5甘特图

Radiantq--jQuery Gantt Package是一个真正跨平台的、基于原生 HTML5/jQuery 的实现,带有 2 个不同的甘特图小部件。 部署在众多垂直领域 无论您的应用程序属于哪个领域,甘特图都是基于时间的信息的理想可视化工具,包括在软件开发、施工、钻井…

JNoteHelper 给你的java swing或桌面程序提供一双翅膀

JNoteHelper 使用swing构建的java程序, 主要基于miglayout,swingx,flatlatf, 本来打算作为个人笔记的助手, 但是事与愿违, 发现理想和现实很骨感. 项目基于windows测试及开发 ,所以运行效果图片都基于windows 截图 1. 项目地址 JNoteHelper github地址 gitee地址 gitcode地址…

玩法专利获批,发布4年《Beat Saber》为何持续火爆

从2018年首次上线以来,《Beat Saber》被大家爱了4年多,直到现在热度未减,依然是史上最赚钱的VR游戏之一。该作最开始的概念,就是用红、蓝两色的光剑,根据箭头方向和节奏去切方块,玩法简单爽快,受…

Qt QSS QSlider样式

本文章主要学习QSlider样式 准备下面几张背景图片: 调小图标 、调大图标 ​、QSlider位置图标 ​QSlider划过的背景图标 ​、QSlider未划过的背景图标 ​最终效果图 自己创建一个QSlider工程,此处省略…… CSDN QT大纲:Qt开发必备技术栈学…

[附源码]java毕业设计鞋店销售管理

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

DM-VERITY流程分析

DM-Verity分析报告 0.问题的表现形式 1.dm-verity的初始化及验证流程 1.1 dm-verity的初始化 初始化dm的log: [ 3.579718] md: Waiting for all devices to be available before autodetect [ 3.586549] md: If you dont use raid, use raidnoautodetect [ 3.594…

Allegro如何录制SCR快捷键操作指导

Allegro如何录制SCR快捷键操作指导 Allegro可以录制SCR快捷键,里面记录了一些操作,类似一个插件,使用的时候可以直接调用,节省时间。下面介绍如何录制 选择file-Script 会出现一个对话框,任意输入一个名字,比如666 然后点击record 比如录制一个打开层面的scr,操作如…