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

设计模式之适配器模式(Adapter)

一、适配器模式介绍

        适配器模式(adapter pattern )的原始定义是:将类的接口转换为客户期望的另一个接口,

        适配器可以让不兼容的两个类一起协同工作。 

        适配器模式是用来做适配,它将不兼容的接口转换为可兼容的接口,让原本由于接口

        不兼容而不能一起工作的类可以一起工作。适配器模式有两种实现方式:类适配器和

        对象适配器。其中,类适配器使用继承关系来实现,对象适配器使用组合关系来实现。

        类适配器模式的耦合度比后者高,且要求程序员了解现有组件库中的相关组件的内部

        结构,所以应用相对较少些。

二、适配器模式原理

       适配器模式(Adapter)包含以下主要角色:

             1)目标(Target)接口:当前系统业务所期待的接口,它可以是抽象类或接口。

             2)适配者(Adaptee)类:适配者即被适配的角色,它是被访问和适配的现存组件库

                  中的组件接口。

            3)适配器(Adapter)类:它是一个转换器,通过继承或引用适配者的对象,把适配

                  者接口转换成目标接口,让客户按目标接口的格式访问适配者。

       类适配器类一般是继承 “适配者类(适配者的具体实现)” 并实现目标接口,而对象适配器

       器类一般是在适配器类中引用适配者类对象;适配器模式结构图如下:

       类适配器模式结构图:

              

       对象适配器模式结构图:

               

三、适配器模式应用示例

        以电脑目前只能读取SD卡的信息为例来看下适配器模式的使用
        一台电脑目前只能读取SD卡的信息,这时我们想要使用电脑读取TF卡的内容, 就需要将TF卡

        加上卡套,转换成SD卡,最后将TF卡中的内容读取出来

1、类适配器模式实现

      实现方式:

             类适配器类继承 “适配者类的具体实现(即TFCardImpl)” 并实现目标接口SDCard

      UML类图如下:

              

      具体代码实现如下:

/*** 类适配器* 以电脑目前只能读取SD卡的信息为例来看下适配器模式的使用* 一台电脑目前只能读取SD卡的信息,这时我们想要使用电脑读取TF卡的内容, 就需要将TF卡加上卡套,转换成SD卡** SD卡接口--目标(Target)接口*/
public interface SDCard {//读取SD卡方法String readSD();//写入SD卡功能void writeSD(String msg);
}/******************************************************** SD卡实现类*********************************************************/
public class SDCardImpl implements SDCard{@Overridepublic String readSD() {String msg = "sd card reading data";return msg;}@Overridepublic void writeSD(String msg) {System.out.println("sd card write data : " + msg);}
}/*** TF卡接口--适配者*/
public interface TFCard {//读取TF卡方法String readTF();//写入TF卡功能void writeTF(String msg);
}/******************************************************** TF卡实现类** *******************************************************/
public class TFCardImpl implements TFCard{@Overridepublic String readTF() {String msg = "tf card reading data";return msg;}@Overridepublic void writeTF(String msg) {System.out.println("tf card write data : " + msg);}
}/******************************************************** 定义适配器类,让SD卡兼容TF卡* 类适配器--通过继承来实现适配********************************************************/
public class SDAdapterTF extends TFCardImpl implements SDCard{@Overridepublic String readSD() {System.out.println("adapter read tf card ");return readTF();}@Overridepublic void writeSD(String msg) {System.out.println("adapter write tf card");writeTF(msg);}
}******************************************************** 电脑类,* 电脑类只能读取sd卡********************************************************/
public class Computer {public String read(SDCard sdCard){return sdCard.readSD();}
}//测试
public class Test {public static void main(String[] args) {Computer computer = new Computer();SDCard sdCard = new SDCardImpl();System.out.println(computer.read(sdCard));System.out.println("========================");SDAdapterTF adapterTF = new SDAdapterTF();System.out.println(computer.read(adapterTF));}
}

2、对象适配器模式实现

      实现方式:

             对象适配器模式可釆用将现有组件库中已经实现的组件引入适配器类中,该类同时实

             现当前系统的业务接口。

      对象适配器模式UML类图如下:

              

      代码实现:

            在类适配器模式的代码基础上我们只需要修改 “适配器类” 就可以了,具体代码如下:

            

/******************************************************** 适配器类* 对象适配器类--通过组合的方式来实现适配********************************************************/
public class SDAdapterTF2 implements SDCard {private TFCard tfCard;public SDAdapterTF2(TFCard tfCard){this.tfCard = tfCard;}@Overridepublic String readSD() {System.out.println("adapter read tf card ");return tfCard.readTF();}@Overridepublic void writeSD(String msg) {System.out.println("adapter write tf card");tfCard.writeTF(msg);}
}

四、适配器模式总结

1、适配器模式优点

      1)将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,无序修改原有结构

      2)增加了类的透明性和复用性,将具体业务实现过程封装在适配者类中,对于客户端类而言

            是透明的,而且提高了适配者的复用性,同一个适配者类可以在多个不同的系统中复用。

      3)灵活性和扩展性都非常好,通过使用配置文件可以很方便的更换适配器,也可以在不修改

            原有代码的基础上增加新的适配器类,符合开闭原则。

     

2、适配器模式缺点

2.1、类适配器的缺点

      1)对于Java等不支持多重继承的语言,一次最多只能适配一个适配者类,不能同时适配

            多个适配者

      2)适配者类不能为最终类,即不能被关键字final修饰

2.2、对象适配器的缺点

      1)与类适配器模式相比较,在该模式下要在适配器中置换适配者类的某些方法比较麻烦。

3、适配器模式适用场景

      1)统一多个类的接口设计时:

            某个功能的实现依赖多个外部系统(或者说类)。通过适配器模式,将它们的接口适配为

            统一的接口定义

      2)需要依赖外部系统时:

            当我们把项目中依赖的一个外部系统替换为另一个外部系统的时候,利用适配器模式,可

            以减少对代码的改动

      3)原有接口无法修改时或者原有接口功能太老旧但又需要兼容时:

            如JDK1.0 Enumeration 到 Iterator 的替换,适用适配器模式保留 Enumeration 类,并将

           其实现替换为直接调用 Itertor

      4)适配不同数据格式时:

            如Slf4j 日志框架,定义打印日志的统一接口,提供针对不同日志框架的适配器

4、代理、桥接、装饰与适配4种设计模式的区别

      代理、桥接、装饰器、适配器,这 4 种模式是比较常用的结构型设计模式。它们的代码结构

      非常相似。但其各自的用意却不同,简单说一下它们之间的关系:

      1)代理模式:

           代理模式在不改变原始类接口的条件下,为原始类定义一个代理类,主要目的是控制访问,

           而非加强功能,这是它跟装饰器模式最大的不同。

      2)桥接模式:

            桥接模式的目的是将接口部分和实现部分分离,从而让它们可以较为容易、也相对独立地

            加以改变。

      3)装饰器模式:

           装饰者模式在不改变原始类接口的情况下,对原始类功能进行增强,并且支持多个装饰器的

           嵌套使用。

      4)适配器模式:

           将一个类的接口转换为客户希望的另一个接口。适配器模式让那些不兼容的类可以一起工作

相关文章:

设计模式之适配器模式(Adapter)

一、适配器模式介绍 适配器模式(adapter pattern )的原始定义是:将类的接口转换为客户期望的另一个接口, 适配器可以让不兼容的两个类一起协同工作。 适配器模式是用来做适配,它将不兼容的接口转换为可兼容的接口,让原本由于接口…...

[git] github管理项目之环境依赖管理

导出依赖到 requirements.txt pip install pipreqs pipreqs . --encodingutf8 --force但是直接使用pip安装不了torch,需要添加源!! pip install -r requirements.txt -f https://download.pytorch.org/whl/torch_stable.html想到一个麻烦的…...

【STM32 Blue Pill编程实例】-SD卡文件读写(SPI接口)

SD卡文件读写(SPI接口) 文章目录 SD卡文件读写(SPI接口)1、SD卡模块介绍2、硬件准备与接线3、模块配置3.1 SPI接口配置3.2 SPI接口的片选信号引脚配置3.3 FATFS配置4、代码实现在本文中,我们将介绍如何将 microSD 卡与 STM32 Blue Pill 连接,并在STM32CubeIDE中对SD卡进行…...

为什么需要软件测试?

软件测试 软件测试是评估和验证计算机程序或系统是否按预期运行的过程。 它涉及执行程序或系统以识别预期结果和实际结果之间的任何错误或差距。 目标是确保软件满足指定的要求,没有缺陷,并在不同场景中可靠地工作。 为什么需要软件测试?…...

成为超人:普通人如何白手起家,富一代和富二代的根本区别是什么?

成为超人:普通人如何白手起家,富一代和富二代的根本区别是什么? 我的问题是事业就讲 10 年装逼学习法失效① 光说不练,还是太懒真正的勤奋,解决温饱后,只专注赚钱这件事 ② 信念飘摇,随波流转万…...

Java 集合 Collection常考面试题

理解集合体系图 collection中 list 是有序的,set 是无序的 什么是迭代器 主要遍历 Collection 集合中的元素,所有实现了 Collection 的集合类都有一个iterator()方法,可以返回一个 iterator 的迭代器。 ArrayList 和 Vector 的区别? ArrayList 可以存放 null,底层是由数…...

C++继承与菱形继承(一文了解全部继承相关基础知识和面试点!)

目的减少重复代码冗余 Class 子类(派生类) : 继承方式 父类(基类) 继承方式共有三种:公共、保护、私有 父类的私有成员private无论哪种继承方式都不可以被子类使用 保护protected权限的内容在类内是可以访问,但是在…...

谷歌DeepMind 德米斯·哈萨比斯 因蛋白质预测AI荣获诺贝尔化学奖

2024年诺贝尔化学奖的一半授予了谷歌DeepMind的联合创始人兼首席执行官德米斯哈萨比斯和公司总监约翰M朱姆珀,以表彰他们在利用人工智能预测蛋白质结构方面的研究成果。另一半奖项则授予华盛顿大学生物化学教授大卫贝克,以表彰他在计算蛋白质设计领域的贡…...

内网笔记大全

内网笔记大全 1、基础命令 Windows 1、net user #查看用户 2、net view #查看在线主机 3、systeminfo #查看操作系统的基本配置 4、ipconfig /all #详细显示当前网络配置信息和网卡信息 5、net localgroup #查看本地组信息 6、net localgroup administrators #查看管理员组 7、…...

peft.LoraConfig()参数说明

LoraConfig()介绍 LoraConfig()是peft库中的一个配置类,用于设置大模型微调方法LoRA(Low-Rank Adaptation)的相关参数。PEFT 库为各种参数高效的微调方法(如 LoRA)提供了封装,以减少微调大模型时的计算资源…...

串口(UART)的FPGA设计(接收与发送模块)

目录 串口基础知识 一、什么是串口?有哪些特点? 二、常见的串口通信协议有哪些?他们有什么区别?...

JSON 格式化工具:快速便捷地格式化和查看 JSON 数据

JSON 格式化工具:快速便捷地格式化和查看 JSON 数据 为什么需要 JSON 格式化工具? 在日常开发和调试中,JSON 是非常常见的数据交换格式。无论是前端与后端的接口调用,还是数据存储和处理,JSON 格式都扮演着重要角色。…...

【星汇极客】STM32 HAL库各种模块开发之1.8TFT屏幕

前言 本人是一名嵌入式学习者,在大学期间也参加了不少的竞赛并获奖,包括:江苏省电子设计竞赛省一、睿抗机器人国二、中国高校智能机器人国二、嵌入式设计竞赛国三、光电设计竞赛国三、节能减排竞赛国三等。 暑假的时候参加了太多的比赛&#…...

Excel中使用SQL语句的四种方法

总结在 Excel 中使用 SQL 语句的四种方法,各种方法都有各自的适用场景,可以选择自己熟悉的或喜欢方式。本文以在 Excel 中操作 MS SQL 数据库的数据为例进行说明。MS SQL 的数据如下,使用微软 SQLExpress 版本。 方法 1: Excel 现…...

目标检测中的损失函数

损失函数是用来衡量模型与数据的匹配程度的,也是模型权重更新的基础。计算损失产生模型权重的梯度,随后通过反向传播算法,模型权重得以更新进而更好地适应数据。一般情况下,目标损失函数包含两部分损失,一个是目标框分…...

list库实现

list库实现的要点&#xff1a; 构建list类时&#xff0c;需要同时构建struct Node来存储节点信息&#xff0c;list类中只存储哨兵位节点信息&#xff0c;迭代器类需要template<T,Ptr,Ref>来构建const和非const迭代器&#xff0c;迭代器中也是存储节点信息。反向迭代器也…...

MFC工控项目实例二十三模拟量输入设置界面

承接专栏《MFC工控项目实例二十二主界面计数背景颜色改变》 1、在SenSet.h文件中添加代码 #include "BtnST.h" #include "ShadeButtonST.h"/ // SenSet dialogclass SenSet : public CDialog { // Construction public:SenSet(CWnd* pParent NULL); //…...

排序算法总结(三)希尔排序

访问www.tomcoding.com网站&#xff0c;学习Oracle内部数据结构&#xff0c;详细文档说明&#xff0c;下载Oracle的exp/imp&#xff0c;DUL&#xff0c;logminer&#xff0c;ASM工具的源代码&#xff0c;学习高技术含量的内容。 如果你在网上搜一下希尔排序&#xff0c;都会告…...

如何迁移 Linux 服务器 第一部分 - 系统准备

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 简介 在许多情况下&#xff0c;您可能需要将数据和操作需求从一个服务器迁移到另一个服务器。您可能需要在新的数据中心实施解决方案&a…...

网络IO模型都有哪些

“网络IO模型有BIO、NIO、AIO ” “他们分别代表什么&#xff0c;有什么区别吗&#xff1f; BIO&#xff1a;同步阻塞IO。 NIO&#xff1a;同步非阻塞IO。 AIO&#xff1a;异步非阻塞IO。 “BIO为什么是同步阻塞IO&#xff0c;他阻塞的是谁跟谁之间的关联&#xff1f;”。 首先…...

linux arm系统烧录

1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 &#xff08;忘了有没有这步了 估计有&#xff09; 刷机程序 和 镜像 就不提供了。要刷的时…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入&#xff0c;一个是通过INMP441麦克风模块采集音频&#xff0c;一个是通过PCM5102A模块播放音频&#xff0c;那如果我们将两者结合起来&#xff0c;将麦克风采集到的音频通过PCM5102A播放&#xff0c;是不是就可以做一个扩音器了呢…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么&#xff1f; WebAssembly&#xff08;WASM&#xff09; 是一种能在现代浏览器中高效运行的二进制指令格式&#xff0c;它不是传统的编程语言&#xff0c;而是一种 低级字节码格式&#xff0c;可由高级语言&#xff08;如 C、C、Rust&am…...

简单介绍C++中 string与wstring

在C中&#xff0c;string和wstring是两种用于处理不同字符编码的字符串类型&#xff0c;分别基于char和wchar_t字符类型。以下是它们的详细说明和对比&#xff1a; 1. 基础定义 string 类型&#xff1a;std::string 字符类型&#xff1a;char&#xff08;通常为8位&#xff09…...

WinUI3开发_使用mica效果

简介 Mica(云母)是Windows10/11上的一种现代化效果&#xff0c;是Windows10/11上所使用的Fluent Design(设计语言)里的一个效果&#xff0c;Windows10/11上所使用的Fluent Design皆旨在于打造一个人类、通用和真正感觉与 Windows 一样的设计。 WinUI3就是Windows10/11上的一个…...

从数据报表到决策大脑:AI重构电商决策链条

在传统电商运营中&#xff0c;决策链条往往止步于“数据报表层”&#xff1a;BI工具整合历史数据&#xff0c;生成滞后一周甚至更久的销售分析&#xff0c;运营团队凭经验预判需求。当爆款突然断货、促销库存积压时&#xff0c;企业才惊觉标准化BI的决策时差正成为增长瓶颈。 一…...

使用python进行图像处理—图像变换(6)

图像变换是指改变图像的几何形状或空间位置的操作。常见的几何变换包括平移、旋转、缩放、剪切&#xff08;shear&#xff09;以及更复杂的仿射变换和透视变换。这些变换在图像配准、图像校正、创建特效等场景中非常有用。 6.1仿射变换(Affine Transformation) 仿射变换是一种…...

创客匠人:如何通过创始人IP打造实现知识变现与IP变现的长效增长?

在流量红利逐渐消退的当下&#xff0c;创始人IP的价值愈发凸显。它不仅能够帮助中小企业及个人创业者突破竞争壁垒&#xff0c;还能成为企业品牌影响力的核心资产。然而&#xff0c;市场上IP孵化机构鱼龙混杂&#xff0c;如何选择一家真正具备长期价值的合作伙伴&#xff1f;创…...

leetcode238-除自身以外数组的乘积

leetcode 238 思路 可以在不使用除法的情况下&#xff0c;利用前缀积和后缀积来实现解答 前缀积&#xff1a;对每个位置&#xff0c;计算当前数字左侧的所有数字的乘积后缀积&#xff1a;对每个位置&#xff0c;计算当前数字右侧的所有数字的乘积 结合这两种思想&#xff0…...

vite ts 配置使用@ 允许js

1.vite.config.ts 配置 import { defineConfig } from vite import vue from vitejs/plugin-vue import { fileURLToPath, URL } from node:url import setup_extend from vite-plugin-vue-setup-extend// https://vite.dev/config/ export default defineConfig({plugins: …...