Spring框架之适配器模式 (Adapter Pattern)

server/2024/11/15 3:54:11/

适配器模式(Adapter Pattern)详解

适配器模式(Adapter Pattern)是一种结构型设计模式,它的主要作用是将一个类的接口转换成客户端期望的另一个接口,使原本由于接口不兼容而无法一起工作的类可以协同工作。适配器模式通常被用来修复已有代码的兼容性问题,尤其是在重用现有类时避免大规模修改代码。

1. 适配器模式的定义

1.1 什么是适配器模式

适配器模式不兼容的接口 进行适配,使得原本不兼容的类能够在一起工作。它就像生活中的电源适配器,可以让不同国家的电器设备在本国的电网环境下正常工作。

1.2 适配器模式的特点
  • 转换接口:将一个类的接口转换为客户端所期望的另一个接口。
  • 兼容性:解决接口不兼容的问题,让原本无法协作的类能够协同工作。
  • 封装旧接口适配器模式常用于将旧系统的接口封装起来,以便与新系统兼容。

2. 适配器模式的结构

适配器模式通常包含以下几个角色:

  1. Target(目标接口)
    • 客户端期望使用的接口。
  2. Adaptee(被适配者)
    • 需要适配的类,其接口与目标接口不兼容。
  3. Adapter(适配器)
    • 将被适配者的接口转换为目标接口的一个包装类。
  4. Client(客户端)
    • 使用目标接口的类。
类图
    +-------------+|   Target    |<--------------------++-------------+                     || + request() |                     |+-------------+                     |^                           ||                           |+--------------+          +----------------+|   Adapter    |--------->|   Adaptee      |+--------------+          +----------------+| + request()  |          | + specificRequest() |+--------------+          +----------------+

3. 适配器模式的分类

适配器模式有两种主要实现方式:

  1. 类适配器(Class Adapter)
    • 使用继承来实现适配器。适配器类继承自 AdapteeTarget
    • 由于 Java 只支持单继承,因此在 Java 中类适配器使用场景较少。
  2. 对象适配器(Object Adapter)
    • 使用组合来实现适配器。适配器类持有一个 Adaptee 对象的引用。
    • 这种方式更加灵活,是推荐的实现方式。

4. 适配器模式的实现

为了更好地理解适配器模式,我们使用一个简单的示例来演示其工作原理。假设我们有一个 AudioPlayer 类,它只能播放 .mp3 文件,现在我们希望它也能播放 .mp4.vlc 文件。

4.1 Java 示例代码:对象适配器
java">// 目标接口
interface MediaPlayer {void play(String audioType, String fileName);
}// 被适配者类(支持 VLC 播放)
class VlcPlayer {public void playVlc(String fileName) {System.out.println("播放 VLC 文件: " + fileName);}
}// 被适配者类(支持 MP4 播放)
class Mp4Player {public void playMp4(String fileName) {System.out.println("播放 MP4 文件: " + fileName);}
}// 适配器类
class MediaAdapter implements MediaPlayer {private VlcPlayer vlcPlayer;private Mp4Player mp4Player;public MediaAdapter(String audioType) {if (audioType.equalsIgnoreCase("vlc")) {vlcPlayer = new VlcPlayer();} else if (audioType.equalsIgnoreCase("mp4")) {mp4Player = new Mp4Player();}}@Overridepublic void play(String audioType, String fileName) {if (audioType.equalsIgnoreCase("vlc")) {vlcPlayer.playVlc(fileName);} else if (audioType.equalsIgnoreCase("mp4")) {mp4Player.playMp4(fileName);}}
}// 具体目标类
class AudioPlayer implements MediaPlayer {private MediaAdapter mediaAdapter;@Overridepublic void play(String audioType, String fileName) {if (audioType.equalsIgnoreCase("mp3")) {System.out.println("播放 MP3 文件: " + fileName);} else if (audioType.equalsIgnoreCase("vlc") || audioType.equalsIgnoreCase("mp4")) {mediaAdapter = new MediaAdapter(audioType);mediaAdapter.play(audioType, fileName);} else {System.out.println("不支持的文件格式: " + audioType);}}
}// 测试客户端
public class AdapterPatternDemo {public static void main(String[] args) {AudioPlayer audioPlayer = new AudioPlayer();audioPlayer.play("mp3", "歌曲.mp3");audioPlayer.play("mp4", "电影.mp4");audioPlayer.play("vlc", "动画.vlc");audioPlayer.play("avi", "短片.avi");}
}

输出结果

java">播放 MP3 文件: 歌曲.mp3
播放 MP4 文件: 电影.mp4
播放 VLC 文件: 动画.vlc
不支持的文件格式: avi

5. 适配器模式的应用场景

适配器模式适合以下场景:

  1. 希望复用一些现有的类,但是类的接口不符合当前系统的需求。
  2. 想要封装一些旧系统的类,以便在新系统中使用。
  3. 使用第三方库,而其接口与项目中定义的接口不兼容。
  4. 希望创建一个可复用的类,使其能够与不相关或不可预见的类协同工作。

6. 适配器模式的优缺点

6.1 优点
  • 提高类的复用性:通过适配器模式,现有类可以与其他类进行协作,而无需修改原始类的代码。
  • 提高类的灵活性和扩展性:通过引入适配器类,可以在不修改现有代码的情况下增加新功能。
  • 解耦目标类与被适配者类:适配器将目标类和被适配者类隔离开来,实现了解耦。
6.2 缺点
  • 增加系统复杂度:引入适配器后,系统会增加额外的适配器类,导致复杂度增加。
  • 不易理解:尤其是系统中存在大量适配器时,可能会导致代码难以理解和维护。
  • 类适配器的实现受限于继承:在 Java 中,类适配器受限于单继承的特性,因此更推荐使用对象适配器。

7. 适配器模式的扩展

7.1 双向适配器
  • 适配器模式可以实现双向适配,即适配器不仅能够将被适配者转化为目标接口,也能将目标接口转化为被适配者接口。
7.2 缺省适配器(Default Adapter)
  • 适用于接口中有多个方法时,想要简化接口的实现。通常通过创建一个抽象类,该抽象类提供这些方法的默认实现,具体类只需重写需要的方法。

8. 适配器模式的实际应用

  1. Java I/O 类库
    • Java 的 InputStreamReaderOutputStreamWriter 就是典型的适配器模式,用于在字节流和字符流之间进行适配。
  2. 数据库连接
    • JDBC 中的 DriverManager 使用适配器模式来适配不同的数据库驱动程序。
  3. Spring 框架
    • Spring 的 HandlerAdapter 适配器用于将不同类型的请求处理器(如 ControllerHttpRequestHandler)适配成统一的处理方式。

9. 总结

适配器模式是一种非常有用的设计模式,尤其是在需要与现有系统集成时。通过适配器模式,可以有效地复用现有代码,同时保持系统的灵活性和扩展性。

  • 优点:提高复用性、解耦、增加灵活性。
  • 缺点:增加复杂度、不易理解。
  • 适用场景:复用现有类、封装旧系统、使用第三方库。


http://www.ppmy.cn/server/141710.html

相关文章

《MYSQL45讲》误删数据怎么办

对误删数据分类的话&#xff0c;有 1.delete 误删行 2.drop table 或者truncate table 语句误删表 3.使用drop database 误删数据库 4.使用rm命令误删整个MYSQL实例 一&#xff0c;误删行 一下操作前置条件是&#xff1a;binlog的格式是row&#xff0c;并且binglog_row_im…

SpringBoot(三)

最佳实践 1.SpringBoot 应用如何编写 引入场景依赖 官方文档 查看自动配置了哪些&#xff08;选做&#xff09; 自己分析&#xff0c;引入场景对应的自动配置一般都生效了配置文件中 debugtrue 开启自动配置报告。 Negative&#xff08;不生效&#xff09;Positive&#xff0…

ctfshow-web入门-反序列化(web260-web264)

目录 1、web260 2、web261 3、web262 4、web263 5、web264 1、web260 要求传入的内容序列化后包含指定内容即可&#xff0c;在 PHP 序列化中&#xff0c;如果键名或值包含 ctfshow_i_love_36D&#xff0c;那么整个序列化结果也会包含这个字符串。 payload&#xff1a; ?…

软件设计师-数据库

上午6分&#xff0c;下午15分&#xff0c;很重要 数据库&#xff0c;长期存储在计算机内的、有组织的、可共享的数据集合&#xff0c;数据库中的数据按照数据模型组织&#xff0c;描述和存储&#xff0c;具有较小的冗余度&#xff0c;较高的数据独立性和易拓展性&#xff0c;并…

【LeetCode】【算法】240. 搜索二维矩阵II

LeetCode 240. 搜索二维矩阵II 题目描述 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性&#xff1a; 每行的元素从左到右升序排列。每列的元素从上到下升序排列。 思路 思路&#xff1a;K神真强啊240.搜索二维矩阵II&#xff0…

Ubuntu22.04安装cuDNN

根据下面地址选择安装即可: 英伟达cuDNN下载 wget https://developer.download.nvidia.com/compute/cudnn/9.5.1/local_installers/cudnn-local-repo-ubuntu2204-9.5.1_1.0-1_amd64.deb sudo dpkg -i cudnn-local-repo-ubuntu2204-9.5.1_1.0-1_amd64.deb sudo cp /var/cudnn-…

Android 开发指南:初学者入门

Android 是全球最受欢迎的移动操作系统之一&#xff0c;为开发者提供了丰富的工具和资源来创建各种类型的应用程序。本文将为你提供一个全面的入门指南&#xff0c;帮助你从零开始学习 Android 开发。 目录 1. 了解 Android 平台[1]2. 设置开发环境[2]3. 学习基础知识[3]4. 创…

什么是上拉和下拉

在电子电路和嵌入式系统中&#xff0c;“上拉”和“下拉”通常指的是上拉电阻&#xff08;pull-up resistor&#xff09;和下拉电阻&#xff08;pull-down resistor&#xff09;。它们是被用于稳定电路输入或输出引脚的电阻器&#xff0c;通过将引脚电位锁定到特定的电压水平来…