设计模式浅析(七) ·适配器模式

设计模式浅析(七) ·适配器模式

日常叨逼叨

java设计模式浅析,如果觉得对你有帮助,记得一键三连,谢谢各位观众老爷😁😁


适配器模式

概念

适配器模式将一个类的接口转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。它经常用来适配现存的类而无需修改其源码

组成
  1. 目标接口(Target Interface):这是客户端所期望的接口,也就是客户端真正需要的接口。目标接口定义了客户端想要使用的方法。
  2. 适配者类(Adaptee Class):这是需要被适配的原始接口。适配者类通常是一个已经存在的类,它包含了一些客户端希望使用的方法,但这些方法的接口与客户端所期望的接口并不一致。
  3. 适配器类(Adapter Class):这是适配器模式的核心部分。适配器类实现了目标接口,并在其内部调用了适配者类的方法。这样,客户端就可以通过调用适配器类的方法来间接调用适配者类的方法,从而实现了接口转换。
主要实现方式

适配器类通常有三种实现方式:

  • 类适配器:通过继承适配者类并实现目标接口来实现。这种方式的缺点是它要求适配者类必须是一个类,而不能是一个接口。此外,由于是通过继承来实现的,因此类适配器只能适配一个适配者类。
  • 对象适配器:通过组合适配者类的实例并实现目标接口来实现。这种方式的优点是它不需要继承适配者类,因此可以适配接口或类。此外,对象适配器可以适配多个适配者类,只需要在适配器类中持有多个适配者类的实例即可。
  • 接口适配器(默认适配器):当不希望实现接口中的所有方法时,可以创建一个抽象类实现该接口,并为所有方法提供默认实现。子类可以选择性地覆盖这些方法。

案例

在这个案例中,我们将创建一个适配器来将一个旧的硬盘驱动器接口适配到新的硬盘驱动器接口。

类适配器实现

首先,我们定义两个接口,OldHardDriveNewHardDrive,分别代表旧的硬盘驱动器接口和新的硬盘驱动器接口:

//新的硬盘启动器接口
public interface NewHardDrive {void read();void write();void connectToSystem();
}
//旧的硬盘启动器接口
public interface OldHardDrive {void readData();void writeData();void connect();
}

定义旧硬盘驱动器的具体实现

public class OldHardDriveImpl implements OldHardDrive {@Overridepublic void readData() {System.out.println("Reading data from old hard drive...");}@Overridepublic void writeData() {System.out.println("Writing data to old hard drive...");}@Overridepublic void connect() {System.out.println("Connecting old hard drive...");}
}

定义适配器

// 适配器类,将OldHardDrive接口适配到NewHardDrive接口
public class HardDriveAdapter extends OldHardDriveImpl implements NewHardDrive {// 由于继承了Adaptee,所以可以直接使用Adaptee的方法// 同时也需要实现Target接口中的方法@Overridepublic void read() {readData();}@Overridepublic void write() {writeData();}@Overridepublic void connectToSystem() {connect();System.out.println("Adapter connected old hard drive to the new system.");}
}

最后创建的测试类可以通过类适配器调用目标接口的方法

public class Client {public static void main(String[] args) {// 创建适配器,将旧硬盘驱动器传递给适配器NewHardDrive adapter = new HardDriveAdapter();// 使用适配器调用新接口的方法adapter.connectToSystem();adapter.read();adapter.write();}
}

在这个例子中,HardDriveAdapter 继承自 OldHardDriveImpl 并实现了 NewHardDrive 接口。当客户端调用 NewHardDrive.connectToSystem() 等方法时,实际上调用的是 HardDriveAdapter 中的 connectToSystem() 等方法,而 connectToSystem() 等方法内部又调用了 OldHardDriveImplconnectToSystem()等 方法。

类适配器的一个潜在缺点是它依赖于适配者类的具体实现,这违反了里氏替换原则。如果适配者类的接口在未来发生变化,类适配器可能需要进行相应的修改,这可能导致代码的不稳定。

因此,在实际应用中,如果可能的话,更推荐使用对象适配器(Object Adapter),因为它不依赖于适配者类的具体实现,而是通过组合(composition)的方式使用适配者类的实例,从而减少了代码之间的耦合性。

对象适配器实现

还是上述的案例,改为使用对象适配器进行实现

//新旧驱动器接口未发生改变
public interface NewHardDrive {void read();void write();void connectToSystem();
}public interface OldHardDrive {void readData();void writeData();void connect();
}
// 旧硬盘驱动器实现也未发生改变
public class OldHardDriveImpl implements OldHardDrive {@Overridepublic void readData() {System.out.println("Reading data from old hard drive...");}@Overridepublic void writeData() {System.out.println("Writing data to old hard drive...");}@Overridepublic void connect() {System.out.println("Connecting old hard drive...");}
}

适配器不再继承旧硬盘驱动器的实现类

// 适配器类,将OldHardDrive接口适配到NewHardDrive接口
public class HardDriveAdapter implements NewHardDrive {private OldHardDrive oldHardDrive;public HardDriveAdapter(OldHardDrive oldHardDrive) {this.oldHardDrive = oldHardDrive;}@Overridepublic void read() {oldHardDrive.readData();}@Overridepublic void write() {oldHardDrive.writeData();}@Overridepublic void connectToSystem() {oldHardDrive.connect();System.out.println("Adapter connected old hard drive to the new system.");}
}

测试类也发生改变

public class Client {public static void main(String[] args) {// 创建旧硬盘驱动器实例OldHardDrive oldHardDrive = new OldHardDriveImpl();// 创建适配器,将旧硬盘驱动器传递给适配器NewHardDrive adapter = new HardDriveAdapter(oldHardDrive);// 使用适配器调用新接口的方法adapter.connectToSystem();adapter.read();adapter.write();}
}

在这个案例中,HardDriveAdapter 类充当了适配器的角色,它实现了 NewHardDrive 接口,并将旧硬盘驱动器的操作封装在其内部。这样,新系统就可以通过 HardDriveAdapter 类来操作旧硬盘驱动器,而无需关心旧接口的具体实现。这就是适配器模式的一个实际应用案例。

优略对比

类适配器和对象适配器都是适配器模式的不同实现方式,它们各有优缺点,适用于不同的场景。以下是类适配器和对象适配器在Java中的优劣势对比:

类适配器(Class Adapter)

优势:

  1. 代码简洁性:类适配器通常只需要一个适配器类,该类继承自适配者类并实现目标接口。这种实现方式相对简单和直接。
  2. 多重继承问题:如果目标接口和适配者类都继承自同一个基类或有相同的接口,那么类适配器就无法工作。在这种情况下,对象适配器是更好的选择。

劣势:

  1. 继承的局限性:类适配器使用了继承,这意味着适配器类不能同时适配多个不兼容的接口,因为Java不支持多重继承。
  2. 扩展性问题:如果适配者类的接口发生改变,可能需要修改适配器类的代码,这违背了开放封闭原则(OCP)。
对象适配器(Object Adapter)

优势:

  1. 灵活性:对象适配器使用对象组合而不是继承,因此可以适配多个不兼容的接口,解决了类适配器中多重继承的问题。
  2. 更好的遵循OCP:由于使用对象组合,当适配者类的接口发生改变时,只需要修改适配器类的代码,而不需要修改客户端代码,这更符合开放封闭原则。
  3. 更好的解耦:对象适配器减少了客户端和适配者之间的耦合度,因为客户端只依赖于目标接口,而不是具体的适配者类。

劣势:

  1. 代码复杂性:与类适配器相比,对象适配器可能需要更多的代码,因为需要创建适配器对象并调用其方法。
  2. 额外的对象创建开销:由于使用了对象组合,每次需要适配时都需要创建一个新的适配器对象,这可能会增加一些额外的内存开销。

代码相关代码可以参考 代码仓库🌐

ps:本文原创,转载请注明出处


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

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

相关文章

前端架构: 脚手架之Chalk和Chalk-CLI使用教程

Chalk Chalk 是粉笔的意思, 它想表达的是,给我们的命令行中的文本添加颜色类似彩色粉笔的功能 在官方文档当中,它的 Highlights 核心特性 Expressive API Highly performant No dependencies Ability to nest styles 256/Truecolor color support Auto-…

提高工作效率,体验ONLYOFFICE办公软件

ONLYOFFICE办公软件 一、前言二、特点完整办公套件协作过程更容易 三、访问地址 一、前言 随着数字化办公的普及,办公软件在我们的工作中扮演着越来越重要的角色。为了提高工作效率,我们需要一个功能强大、易于使用的办公软件。ONLYOFFICE作为一款全功能…

分布式系统一致性与共识算法

分布式系统的一致性是指从系统外部读取系统内部的数据时,在一定约束条件下相同,即数据(元数据,日志数据等等)变动在系统内部各节点应该是一致的。 一致性模型分为如下几种: ① 强一致性 所有用户在任意时…

安装SSH连接工具

连接Linux 1). 打开finalShell 2). 建立连接 Linux目录结构 在Linux系统中,也是存在目录的概念的,但是Linux的目录结构和Windows的目录结构是存在比较多的差异的 在Windows目录下,是一个一个的盘符(C盘、D盘、E盘),目…

东南大学easyconnect无法连接校园网的解决方案

一般没设置柯学上网的电脑都没什么问题 1.网络异常 加上clash直连即可

标准版无法支持tts,所以替换/bin/oracle文件试试?

之前我们确认了oracle标准版不支持tts-CSDN博客,那有没有办法绕过这个问题呢? 测试通过将$ORACLE_HOME/bin/oracle的企业版文件替换掉标准版的oracle文件之后,发现可以做tts操作。 缺点在线mv oracle会是alert日志大量告警,此时…

SpringBoot 使用 JWT 保护 Rest Api 接口

用 spring-boot 开发 RESTful API 非常的方便,在生产环境中,对发布的 API 增加授权保护是非常必要的。现在我们来看如何利用 JWT 技术为 API 增加授权保护,保证只有获得授权的用户才能够访问 API。 一、Jwt 介绍 JSON Web Token (JWT)是一个开…

五种多目标优化算法(NSWOA、MOJS、MOAHA、MOPSO、NSGA2)性能对比(提供MATLAB代码)

一、5种多目标优化算法简介 1.1NSWOA 1.2MOJS 1.3MOAHA 1.4MOPSO 1.5NSGA2 二、5种多目标优化算法性能对比 为了测试5种算法的性能将其求解9个多目标测试函数(zdt1、zdt2 、zdt3、 zdt4、 zdt6 、Schaffer、 Kursawe 、Viennet2、 Viennet3)&#xff0…

设计模式-创建型模式-抽象工厂模式

抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,它是一种对象创建型模式。 由于工厂方法模式中的每个工厂只生产一类产品&…

stm32——hal库学习笔记(DAC)

这里写目录标题 一、DAC简介(了解)1.1,什么是DAC?1.2,DAC的特性参数1.3,STM32各系列DAC的主要特性 二、DAC工作原理(掌握)2.1,DAC框图简介(F1)2.2…

《穿越科技的前沿:计算机专业必看的电影盛宴》

文章目录 每日一句正能量前言电影推荐推荐一:《黑客帝国》推荐二:《社交网络》推荐三:《源代码》推荐四:《谍影重重》系列推荐五:《旋转木马》 技术与主题后记 每日一句正能量 一个人的一生,就是一座有了年…

探索Go语言中的HTTP路由和中间件

在Go语言中,HTTP路由和中间件是实现Web应用程序核心功能的关键组件。路由负责将传入的HTTP请求分发到适当的处理函数,而中间件则提供了一种在请求处理过程中插入额外逻辑的机制。 HTTP路由 在Go中,net/http标准库提供了基本的路由功能&…

红队-主机发现端口扫描

NMAP扫描(kali) 查看nmap帮助 nmap --help 主机发现,扫描整个C段 sudo nmap -sn 192.168.2.0/24 端口扫描,最小速度10000,扫描全部端口(-p-) sudo nmap --min-rate 10000 -p- 192.168.200.24410000是权衡过的速度…

WebGIS开发技术岗真实面经分享!

24春招在即,很多人都已经在开始踏上面试的征程 面对日益严峻的就业环境,想获得更好的工作机会,没有捷径可走,只有不断提升才是硬道理。在此小编分享几个网友GIS开发岗真实的面试经历,希望对正在求职的你,有…

六、回归与聚类算法 - 线性回归

目录 1、线性回归的原理 1.1 应用场景 1.2 什么是线性回归 1.2.1 定义 1.2.2 线性回归的特征与目标的关系分析 2、线性回归的损失和优化原理 2.1 损失函数 2.2 优化算法 2.2.1 正规方程 2.2.2 梯度下降 3、线性回归API 4、回归性能评估 5、波士顿房价预测 5.1 流…

Nginx 和 Apache 的比较

Nginx和Apache的对比 Nginx和Apache的优缺点比较 (1)nginx相对于apache的优点 ①轻量级,同样起web服务,比apache占用更少的内存及资源 ②抗并发,nginx处理请求是异步非阻塞的,而apache是阻塞型的在高并发下,nginx能保持…

yolov5-tracking-xxxsort yolov5融合六种跟踪算法(二)--目标识别

本次开源计划主要针对大学生无人机相关竞赛的视觉算法开发。 开源代码仓库链接:https://github.com/zzhmx/yolov5-tracking-xxxsort.git 先按照之前的博客配置好环境: yolov5-tracking-xxxsort yolov5融合六种跟踪算法(一)–环境配…

【快速搞定Webpack5】处理样式资源(三)

本次内容我们将学习使用webpack如何处理css、less、sass、scss等样式资源 介绍 webpack本身是不能识别样式资源的,所以我们需要借助loader包来帮助webpack解析样式资源 我们找loader都应该去官方文档中查找对应的loader,然后学习使用。 官方文档找不到…

Linux中安装Nginx及日常配置使用

高性能的http服务器/反向代理服务器。官方测试支持5万并发,CPU、内存等消耗较低且运行稳定 使用场景 Http服务器。 Nginx可以单独提供Http服务,做为静态网页的服务器。虚拟主机。 可以在一台服务器虚拟出多个网站。反向代理与负载均衡。 Nginx做反向代理…

LaWGPT—基于中文法律知识的大模型

文章目录 LaWGPT:基于中文法律知识的大语言模型数据构建模型及训练步骤两个阶段二次训练流程指令精调步骤计算资源 项目结构模型部署及推理 LawGPT_zh:中文法律大模型(獬豸)数据构建知识问答模型推理训练步骤 LaWGPT:基…