设计模式—适配器模式

概念:

适配器模式(有时候也称包装样式或者包装)将一个类的接口适配成用户所期待的。一个适配允许通常因为接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存在的类中。

本章代码: 小麻雀icknn/设计模式练习 - Gitee.com

结构:

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

UML类图:

 例: 

 目标(Target)接口: 

package com.study.main.Adapter;

public interface Usb {
   String useUsbMethod();
}

 适配器(Adapter)类: 

package com.study.main.Adapter;

public class ChangeAdapter implements Usb{
    AndroidTypeC androidTypeC;
    public ChangeAdapter() {
        this.androidTypeC = new AndroidTypeC();
    }

    @Override
    public String useUsbMethod() {
        return androidTypeC.myUsbMethods();
    }
}

适配者(Adaptee)类: 

package com.study.main.Adapter;

public class AndroidTypeC {
    String myUsbMethods(){
        return "Android TypeC 接口";
    }
}
package com.study.main.Adapter;

public class Android implements Usb{
    @Override
    public String useUsbMethod() {
        return "Android USB 适配 Mini-USB";
    }
}

运行&结果: 

场景分析 :

适配器模式一般常用的使用场景有:

  • 原有接口无法修改时;
  • 原有接口功能太老旧时;
  • 统一多个类的接口设计时;
  • 需要过渡升级旧接口时;
  • 需要依赖外部系统时;
  • 适配不同数据格式时;
  • 不同接口协议转换时。

适配器模式的使用场景主要有这两大类:第一类就是原有接口功能不满足现有要求,需要在兼容老接口的同时做适当的扩展;第二类是有相似性的多个不同接口之间做功能的统一

适配器在源码中的应用 : 

在inputStreamReader中适配了inpuStream类并使用了里面的方法把InputStream对象转换成了BufferReader

适配器模式优缺点:

优点:

  • 将目标类和具体适配者类解耦。 通过引入一个适配器类来兼容现有的目标类,重用原有类功能的同时扩展新功能,而无须修改原有目标类代码,这样很好地避免了具体适配者类和目标类的直接耦合。
  • 增加了类的透明性。 具体的适配者类中新增功能只影响适配者类,而对于使用目标类的客户端类来说是透明的(使用目标类接口),客户端的调用逻辑不会受到影响。
  • 满足里氏替换原则 具体适配者类通过适配器类与目标类进行交互,那么适配器类只要不影响目标类的接口功能,具体适配者类无论使用什么样的新功能,都能很方便快速地进行替换。
  • 符合开闭原则 由于具体适配者类要么是适配器类的子类,要么和适配器类是组合关系,所以对目标类没有修改,满足开闭原则。
  • 统一多个类或接口 一个适配器类可以把多个不同的具体适配者类和子类,都适配到同一个目标类上,如果这个目标类是一个新类,那么就是间接实现了统一多个类或接口的功能。

缺点:

  • 一次只能适配一个抽象类或接口
    像 Java、C# 等编程语言是不支持多重继承的,那么在进行适配时,一次最多只能适配一个适配者类。另外,目标类只能为抽象类或接口,不能为具体实例类,这样会在适配时增加很多类文件和代码量,如果适配的类或接口比较多,那么就会增加代码的理解难度。
  • 过度嵌套会导致接口臃肿 适配器有一个最大的弊端就是,一旦不停地在同一个目标类上增加适配器,就会很容易让接口变得越来越臃肿。你见过一个接口被适配 20 次的情景吗?我前不久在工作中就见过,其实这也是开闭原则极端副作用的某种体现。因为不想去修改原有接口,所以就不断使用新接口适配,而维护接口的人又在不断变化,于是就继续按照这个不修改的思路维护下去,表面上的确符合开闭原则,但实际上只不过是将风险不断隐藏罢了。一旦原始接口(目标类)功能下线后,这个适配链条造成的影响会非常大。
  • 目标接口依赖太多适配接口,修改目标接口会导致所有适配接口都需要定制修改。 本来适配器模式是为了解耦,但是如果适配太多接口,就会演变为另一种定制化的开发。比如,上游平台商家提供的接口变更,导致下游使用方频繁变更接口。再比如,消息组件接口的变更导致所有引用消息组件的适配器全部都需要修改。

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

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

相关文章

微服务---Eureka注册中心

目录 一、服务中的提供者与消费者 二、Eureka工作流程 三、搭建Eureka服务 四、服务拉取 五、总结 1.搭建EurekaServer 2.服务注册 3.服务发现 一、服务中的提供者与消费者 服务提供者:一次业务中,被其他微服务调用的服务。即提供接口给其他微服务。…

SpringBoot整合【RocketMQ】

目录 1.POM文件添加依赖及yml配置 2.RocketmqUtil 3.生产者&#xff08;异步发送示例&#xff09; 4.消费者 5.测试 1.POM文件添加依赖及yml配置 <dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-spring-boot-starter&l…

Android使用Sensor.TYPE_STEP_COUNTER计步器传感器进行步数统计

1、首先&#xff0c;申请权限 必须声明 ACTIVITY_RECOGNITION 权限&#xff0c;以便您的应用在运行 Android 10 (API 级别 29) 或更高版本的设备上使用此传感器。 Manifest.xml也记得声明 if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {Log.d(TAG, "[权限]&quo…

Elasticsearch:从 ES|QL 到 Python 数据帧

在我之前的文章 “Elasticsearch&#xff1a;ES|QL 查询展示”&#xff0c;我展示了如何在 Kibana 中使用 ES|QL 对索引来进行查询及统计。在很多的情况下&#xff0c;我们需要在客户端中来对数据进行查询&#xff0c;那么我们该怎么办呢&#xff1f;我们需要使用到 Elasticsea…

挖掘NCDA设计大赛获奖作品的成功之道:探讨表情包设计竞争力的关键因素

第12届大赛简介 - 未来设计师全国高校数字艺术设计大赛&#xff08;NCDA&#xff09;开始啦&#xff01;今天我们就特地来说说它的虚拟IP及表情包设计的命题之一的表情包设计选项&#xff0c;为了使大家更好地参加本次比赛&#xff0c;本文特别整理了往届NCDA的表情包设计获奖作…

(每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理 第13章 项目资源管理(五)

项目建议与立项申请、初步可行性研究、详细可行性研究、评估与决策是项目投资前使其的四个阶段。在实际工作中&#xff0c;初步可行性研究和详细可行性研究可以依据项目的规模和繁简程度合二为一&#xff0c;但详细可行性研究是不可缺少的。升级改造项目制作初步和详细研究&…

基于Python实现银行卡识别

在本文中将介绍如何使用Python和深度学习技术来实现银行卡识别功能。银行卡识别是一个在金融、安全等领域具有重要应用的问题&#xff0c;将使用深度学习模型来实现银行卡图像的识别和分类。 目录 引言数据集准备预处理和特征提取模型选择与训练模型评估与性能优化部署与应用 引…

【Leetcode 438】找到字符串中所有字母异位词 —— 滑动窗口

438. 找到字符串中所有字母异位词 给定两个字符串s和p&#xff0c;找到s中所有p的 异位词 的子串&#xff0c;返回这些子串的起始索引。不考虑答案输出的顺序。 异位词 指由相同字母重排列形成的字符串&#xff08;包括相同的字符串&#xff09;。 示例 1: 输入: s “cbaeb…

DRAM 是什么?一文看懂DRAM 产业完整介绍!

全球经济前景不乐观&#xff0c;导致 DRAM 需求下滑&#xff0c;随着 DRAM 价格的连续下跌&#xff0c;三星、海力士等相关大厂的业绩前景都不被看好。那究竟 DRAM 到底是什么产品&#xff1f; DRAM 是什么&#xff1f; DRAM 其实就是我们一般生活中常常在讲的“存储”&#x…

回溯算法05-分割回文子串(Java)

5.分割回文子串 题目描述 给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个子串都是 回文串 。返回 s 所有可能的分割方案。 回文串 是正着读和反着读都一样的字符串。 示例 1&#xff1a; 输入&#xff1a;s "aab" 输出&#xff1a;[[…

云服务器99元一年阿里云和腾讯云对比,明智选择!

腾讯云服务器99元一年是真的吗&#xff1f;真的&#xff0c;只是又降价了&#xff0c;现在只要61元一年&#xff0c;配置为2核2G3M轻量应用服务器&#xff0c;40GB SSD盘&#xff0c;腾讯云百科txybk.com分享腾讯云官方活动购买链接 https://curl.qcloud.com/oRMoSucP 活动打开…

Clion调试QT程序qDebug()、cout控制台无输出的可能解决方法

qDebug()不输出 在当前项目配置中添加一个环境变量 方法一、单独为配置 QT_ASSUME_STDERR_HAS_CONSOLE1 方法二、全局配置&#xff08;系统变量&#xff09; 一劳永逸 效果 cout不输出 Clion在debug调试C/C的时候&#xff0c;printf/cout不会实时输出情况 结果同上~ 谢阅…

【视觉AIGC识别】误差特征、人脸伪造检测、其他类型假图检测

视觉AIGC识别——人脸伪造检测、误差特征 不可见水印 前言视觉AIGC识别【误差特征】DIRE for Diffusion-Generated Image Detection方法扩散模型的角色DIRE作为检测指标 实验结果泛化能力和抗扰动 人脸伪造监测&#xff08;Face Forgery Detection&#xff09;人脸伪造图生成 …

进程间通信之信号灯 || 网络协议UDP/TCP || 三次握手四次挥手

在线程通信中由于数据段等内存空间的共用性&#xff0c;导致同时访问时资源竞争的问题&#xff0c;在线程中我们使用信号量的申请和释放&#xff0c;在防止资源竞争的产生。在进程间的通信中&#xff0c;有信号灯的概念。搭配共享内存实现进程同步。 有名信号量: 1.创建 …

请你简单说一下 Mysql 的事务隔离级别

什么情况&#xff0c;写了 5 年的 CRUD&#xff0c;还搞不清楚 Mysql 的事务隔离级别&#xff0c;难怪第一面就被刷下来。 一个 5 年经验的粉丝&#xff0c;在一个公司干了 5 年&#xff0c;觉得自己特厉害&#xff0c;什么都能搞定&#xff0c;结果每次一到技术面就被刷。问我…

滴滴基于 Clickhouse 构建新一代日志存储系统

ClickHouse 是2016年开源的用于实时数据分析的一款高性能列式分布式数据库&#xff0c;支持向量化计算引擎、多核并行计算、高压缩比等功能&#xff0c;在分析型数据库中单表查询速度是最快的。2020年开始在滴滴内部大规模地推广和应用&#xff0c;服务网约车和日志检索等核心平…

Unity UGUI之InputField(TMP)基本了解

Unity的InputField组件是用于在Unity中创建可供用户输入文本的输入框的UI组件。通过InputField组件&#xff0c;可以让用户在运行时输入文本&#xff0c;比如用户名、密码、搜索关键字等。其中TMP版本的InputField是基于TextMeshPro的InputField组件&#xff0c;提供了更多的文…

【Java JVM】Class 文件的加载

Java 虚拟机把描述类的数据从 Class 文件加载到内存, 并对数据进行校验, 转换解析和初始化, 最终形成可以被虚拟机直接使用的 Java 类型, 这个过程被称作虚拟机的类加载机制。 与那些在编译时需要进行连接的语言不同, 在 Java 语言里面, 类的加载, 连接和初始化过程都是在程序…

java IO 01 输入和输出,File在磁盘上的创建,File的函数,目录

输入和输出&#xff1a; 输入和输出都是从内存的角度出发的&#xff0c;也可以说是java程序角度。 输入到内存的&#xff08;java程序的&#xff09;都是输入 从内存的&#xff08;java程序的&#xff09;都是输出 02. import java.io.File; import java.io.IOException;pu…

vue2源码分析-vue入口文件global-api分析

文章背景 vue项目开发过程中,首先会有一个初始化的流程,以及我们会使用到很多全局的api,如 this.$set this.$delete this.$nextTick,以及初始化方法extend,initUse, initMixin , initExtend, initAssetRegisters 等等那它们是怎么实现,让我们一起来探究下吧 源码目录 global-…