【深入了解设计模式】适配器设计模式

news/发布时间2024/5/16 6:06:39

在这里插入图片描述

适配器设计模式

适配器设计模式是一种结构型设计模式,用于将一个类的接口转换成客户端所期望的另一个接口,从而使得原本由于接口不兼容而不能一起工作的类能够一起工作。适配器模式通常用于以下场景:

  1. 现有接口与需求不匹配:当需要使用的类的接口与当前系统的接口不匹配时,可以创建一个适配器来进行转换。

  2. 类的功能需要增强:有时候,为了增强现有类的功能而不修改原有代码,可以使用适配器模式。

概述

如果去欧洲国家去旅游的话,他们的插座如下图最左边,是欧洲标准。而我们使用的插头如下图最右边的。因此我们的笔记本电脑,手机在当地不能直接充电。所以就需要一个插座转换器,转换器第1面插入当地的插座,第2面供我们充电,这样使得我们的插头在当地能使用。生活中这样的例子很多,手机充电器(将220v转换为5v的电压),读卡器等,其实就是使用到了适配器模式。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

定义:

​ 将一个类的接口转换成客户端希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。

​ 适配器模式分为类适配器模式对象适配器模式,前者类之间的耦合度比后者高,且要求程序员了解现有组件库中的相关组件的内部结构,所以应用相对较少些。

结构

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

  • 目标(Target)接口:当前系统业务所期待的接口,它可以是抽象类或接口。
  • 被适配者(Adaptee):需要被适配的类。它定义了适配器所需的原始接口。
  • 适配器(Adapter)类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。

适配器模式的实现可以分为两种方式:

  • 类适配器模式:通过继承被适配类和实现目标接口来实现适配器。这种方式需要多重继承或接口实现,不过在一些编程语言中并不支持多重继承,因此并不常用。

  • 对象适配器模式:通过在适配器类中组合或聚合被适配类的实例来实现适配器。这种方式更加灵活,因为它可以适配多个类而不仅限于单一类。

适配器设计模式能够很好地解决不同接口之间的兼容性问题,使得原本不兼容的类能够协同工作,提高了代码的复用性和灵活性。

类适配器模式

实现方式:定义一个适配器类来实现当前系统的业务接口,同时又继承现有组件库中已经存在的组件。

【例】读卡器

现有一台电脑只能读取SD卡,而要读取TF卡中的内容的话就需要使用到适配器模式。创建一个读卡器,将TF卡中的内容读取出来。

代码如下:

/*** @author OldGj 2024/02/23* @version v1.0* @apiNote 电脑类*/
public class Computer {// 向SD卡中写数据(目标接口只能是SDCard)public void writeSD(SDCard sdCard, String msg) {sdCard.writeMsg(msg);}// 从SD卡中读取数据(目标接口只能是SDCard)public String readSD(SDCard sdCard) {return sdCard.readMsg();}
}
/*** @author OldGj 2024/02/23* @version v1.0* @apiNote 目标接口 - SD卡接口*/
public interface SDCard {// 向SD卡中写数据void writeMsg(String msg);// 从SD卡中读数据String readMsg();}
/*** @author OldGj 2024/02/23* @version v1.0* @apiNote 目标接口实现类 - SDCard实现类*/
public class SDCardImpl implements SDCard{@Overridepublic void writeMsg(String msg) {System.out.println("write msg to sd card"+msg);}@Overridepublic String readMsg() {return "read msg from sd card";}
}
/*** @author OldGj 2024/02/23* @version v1.0* @apiNote 适配者 - TFCard*/
public interface TFCard {// 向TF卡中写数据void writeMsg(String msg);// 从TF卡中读数据String readMsg();}
/*** @author OldGj 2024/02/23* @version v1.0* @apiNote 具体适配者 - TFCard具体实现类*/
public class TFCardImpl implements TFCard{@Overridepublic void writeMsg(String msg) {System.out.println("write msg to tf card"+msg);}@Overridepublic String readMsg() {return "read msg from tf card";}
}

/*** @author OldGj 2024/02/23* @version v1.0* @apiNote 适配器类 继承被适配者类 实现目标接口*/
public class SDAdapterTF extends TFCardImpl implements SDCard{@Overridepublic void writeMsg(String msg) {super.writeMsg(msg);}@Overridepublic String readMsg() {return super.readMsg();}
}
/*** @author OldGj 2024/02/23* @version v1.0* @apiNote 客户端 - 测试类*/
public class Client {public static void main(String[] args) {Computer computer = new Computer();SDCard sdCard = new SDCardImpl();String s = computer.readSD(sdCard);System.out.println(s);System.out.println("=============");// 通过适配器,将TF卡转换为实现SD接口的适配器SDAdapterTF adapterTF = new SDAdapterTF();// 读取适配器中的数据String s1 = computer.readSD(adapterTF);System.out.println(s1);}
}

类适配器模式违背了合成复用原则。类适配器是客户类有一个接口规范的情况下可用,反之不可用。

对象适配器模式

实现方式:对象适配器模式可釆用将现有组件库中已经实现的组件引入适配器类中,该类同时实现当前系统的业务接口。

【例】读卡器

我们使用对象适配器模式将读卡器的案例进行改写。

类适配器模式的代码,我们只需要修改适配器类(SDAdapterTF)和测试类。

/*** @author OldGj 2024/02/23* @version v1.0* @apiNote 适配器类 继承适配者类 实现目标接口*/
public class SDAdapterTF implements SDCard {private TFCard tfCard;public SDAdapterTF(TFCard tfCard) {this.tfCard = tfCard;}@Overridepublic void writeMsg(String msg) {tfCard.writeMsg(msg);}@Overridepublic String readMsg() {return tfCard.readMsg();}
}
/*** @author OldGj 2024/02/23* @version v1.0* @apiNote 客户端 - 测试类*/
public class Client {public static void main(String[] args) {Computer computer = new Computer();SDCard sdCard = new SDCardImpl();String s = computer.readSD(sdCard);System.out.println(s);System.out.println("=============");// 将TF卡传入适配器中SDAdapterTF sdAdapterTF = new SDAdapterTF(new TFCardImpl());String s1 = computer.readSD(sdAdapterTF);System.out.println(s1);}
}

注意:还有一个适配器模式是接口适配器模式。当不希望实现一个接口中所有的方法时,可以创建一个抽象类Adapter ,实现所有方法。而此时我们只需要继承该抽象类即可。

应用场景

  • 以前开发的系统存在满足新系统功能需求的类,但其接口同新系统的接口不一致。
  • 使用第三方提供的组件,但组件接口定义和自己要求的接口定义不同。

JDK中的适配器模式:

当涉及字符流(Reader)和字节流(InputStream)之间的适配时,通常会使用适配器模式。这种适配器模式的目的是让字符流和字节流能够协同工作,尽管它们的接口不同。

  1. Reader(字符流)Reader 是 Java 中用于读取字符流的抽象基类。它定义了读取字符数据的一系列方法,如 read()close() 等。字符流是以字符为单位进行读取和写入的,对文本数据的处理更为方便。

  2. InputStream(字节流)InputStream 是 Java 中用于读取字节流的抽象基类。它定义了读取字节数据的一系列方法,如 read()close() 等。字节流是以字节为单位进行读取和写入的,适用于处理二进制数据。

  3. InputStreamReader(适配器)InputStreamReader 是 Java 中用于将字节流转换为字符流的适配器类。它实现了 Reader 接口,并包装了一个 InputStream 对象。InputStreamReader 通过在字节流和字符流之间进行转换,使得字符流能够读取字节流中的数据。它的作用就是将字节流适配成字符流,使得原本不兼容的字符流和字节流能够一起工作。

在使用 InputStreamReader 时,它会接受一个 InputStream 对象作为参数,并将该对象转换为字符流,因此它充当了字符流和字节流之间的适配器。这样一来,当我们需要使用字符流操作时,可以直接使用 Reader 接口及其实现类,而不必直接操作字节流。InputStreamReader 负责将底层的字节流适配成字符流,从而实现了字符流和字节流之间的适配。

总而言之,ReaderInputStream 之间的适配器模式的典型应用就是通过 InputStreamReader 将字节流适配成字符流,使得字符流和字节流能够协同工作,这是适配器模式在 Java IO 中的一个典型应用。

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

如若内容造成侵权/违法违规/事实不符,请联系编程老四网进行投诉反馈email:xxxxxxxx@qq.com,一经查实,立即删除!

相关文章

PMP项目管理考试要注意些什么?

PMP考试和PMP备考过程中应该注意哪些问题? PMP备考完成后就要迎接实战考试了,考试前千万不要有多余的想法,顺其自然就行了,我想大家各种紧张、各种忧虑的原因大抵是因为考试成本考,担心考不过,其实只要你在…

基于IDEA+Mysql+Tomcat+Vue开发的框架的汇美食电子商城的设计与实现

基于IDEAMysqlTomcatVue开发的框架的汇美食电子商城的设计与实现 项目介绍💁🏻 随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了基于Vue框架的汇美食电子商城的设计与实现的开发全过程。通过分…

GPT+Python+GEE+ENVI高光谱,多光谱等成像遥感技术应用

原文链接:GPTPythonGEEENVI高光谱,多光谱等成像遥感技术应用https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247594986&idx2&sn770b456d434fdbada22e425b35affe08&chksmfa82320dcdf5bb1b9838b03e13381bdf38ea1b24ebc03526293756a…

python 基础知识点(蓝桥杯python科目个人复习计划51)

今日复习计划:做复习题 例题1:大石头的搬运工 问题描述: 在一款名为“大石头的搬运工”的游戏中,玩家需要 操作一排n堆石头,进行n - 1轮游戏。 每一轮,玩家可以选择一堆石头,并将其移动到任…

Js如何判断两个数组是否相等?

本文目录 1、通过数组自带方法比较2、通过循环判断3、toString()4、join()5、JSON.stringify() 日常开发,时不时会遇到需要判定2个数组是否相等的情况,需要实现考虑的场景有: 先判断长度,长度不等必然不等元素位置其他情况考虑 1…

OpenCvSharp Tracker 目标追踪

目录 效果 项目 代码 下载 C# OpenCvSharp Tracker 目标追踪 效果 项目 代码 using OpenCvSharp; using OpenCvSharp.Extensions; using OpenCvSharp.Tracking; using System; using System.Drawing; using System.Reflection; using System.Windows.Forms;namespace C__…

go环境安装-基于vscode的Windows安装

1、vscode安装 官网链接:https://code.visualstudio.com/ 选择相应的版本,这里选择Windows下的 下载得到一个VSCodeUserSetUp-x64的可执行文件,双击执行,选择要安装的路径,下一步。 2、go语言安装 官网链接&#x…

java面试(网络)

TCP和UDP有什么区别?TCP三次握手不是两次? TCP:面向连接,可靠的,传输层通信协议。点对点,占用资源多,效率低。 UDP:无连接,不可靠,传输层通信协议。广播&…

【杭州游戏业:创业热土,政策先行】

在前面的文章中,我们探讨了上海、北京、广州、深圳等城市的游戏产业现状。现在,我们切换视角,来看看另一个游戏创业热土——杭州的发展情况 最近第19届亚运会在杭州举办,本次亚运会上,电子竞技首次获准列为正式比赛项…

RAW 编程接口 TCP 简介

一、LWIP 中 中 RAW API 编程接口中与 TCP 相关的函数 二、LWIP TCP RAW API 函数 三、LwIP_Periodic_Handle函数 LwIP_Periodic_Handle 函数是一个必须被无限循环调用的 LwIP支持函数,一般在 main函数的无限循环中调用,主要功能是为 LwIP各个模块提供…

flink源码分析 - 获取调用位置信息

flink版本: flink-1.11.2 调用位置: org.apache.flink.streaming.api.datastream.DataStream#flatMap(org.apache.flink.api.common.functions.FlatMapFunction<T,R>) 代码核心位置: org.apache.flink.api.java.Utils#getCallLocationName() flink算子flatmap中调用了一…

如何让电脑待机而wifi不关的操作方法!!

1、一台电脑如果一天不关机&#xff0c;大约消耗0.3度电。 一般一台电脑的功耗约为250-400W&#xff08;台式机&#xff09;。 一台电脑每月的耗电量&#xff1a;如果是每小时300W每天10小时每月30天90KW&#xff0c;即90千瓦时的电。 这只是保守估计。 2、使用完毕后正常关闭…

ARM处理器有哪些工作模式和寄存器?各寄存器作用是什么?ARM异常中断处理流程?

《嵌入式工程师自我修养/C语言》系列——ARM处理器有哪些工作模式和寄存器&#xff1f;各寄存器作用是什么&#xff1f; 一、ARM处理器的工作模式及寄存器1.1 ARM处理器的工作模式1.2 ARM处理器中的寄存器 二、ARM 异常中断处理2.1 什么是异常&#xff1f;异常向量表是什么&…

Python爬虫进阶:爬取在线电视剧信息与高级检索

简介&#xff1a; 本文将向你展示如何使用Python创建一个能够爬取在线电视剧信息的爬虫&#xff0c;并介绍如何实现更高级的检索功能。我们将使用requests和BeautifulSoup库来爬取数据&#xff0c;并使用pandas库来处理和存储检索结果。 目录 一、爬取在线电视剧信息 …

es6 中的生成器 generator / 迭代器 / async /await 到底是个啥,使用场景

生成器 generator 到底是个啥 是一个函数 可以用来遍历数据结构是解决异步编程的一种方案进行数据流的生成和控制协程和状态机返回一个生成器对象/可迭代对象 生成器对象&#xff1a; 生成器对象是由生成器函数返回的对象&#xff0c;它符合迭代器协议&#xff08;Iterator Pr…

ChatGpt的初步认知(认知搬运工)

前言 ChatGpt火了有一段时间了&#xff0c;对各行各业也有了一定的渗透&#xff0c;当然发展过程中也做了一些安全约束&#xff0c;今天主要是来跟大家分享下关于chatGpt的初步认知。 一、chatGpt是什么&#xff1f; ChatGPT&#xff0c;全称聊天生成预训练转换器&#xff08;英…

K8S部署Java项目 pod的logs报错为:Error: Unable to access jarfile app.jar

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

react中使用echarts

先上一张效果图 React中 配置属性如下&#xff0c;可直接粘贴使用 import React, { useEffect, useMemo, useState } from react import * as echarts from echarts import ReactECharts from echarts-for-reactconst LineChart (props: any) > {const option {color: [#…

2024年2月26日

2024年2月26日&#xff0c;周一&#xff0c;早上要上班。 做了一个梦、梦见我找到我最爱的那个女孩&#xff0c;刚好梦里她应该也喜欢我吧&#xff0c;我们相拥&#xff0c;她笑的好美&#xff0c;他要带我去见她父亲商量我们的未来&#xff0c;可是她在路上变成了螃蟹&#xf…

惠尔顿安全审计系统任意文件读取漏洞

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…
推荐文章