适配器模式(Adapter Pattern)
00 分钟
2024-11-18
标签
 
💡
适配器模式是一种结构型设计模式,通过适配器将一个类的接口转换成客户端期望的另一种接口,使得不兼容的接口可以一起工作。它通常在希望复用现有类但接口不匹配时使用。

定义

适配器模式通过创建一个中间类(适配器)连接目标接口和现有接口,使得两个接口可以协同工作。适配器既可以是类适配器(基于继承)也可以是对象适配器(基于组合)。

使用场景

  1. 系统需要使用现有的类,但该类的接口不符合需求。
  1. 需要通过统一的接口调用多个不同的接口。
  1. 希望封装和解耦不同模块之间的依赖关系。

结构

适配器模式包括以下角色:
  • 目标接口(Target):定义客户端期望的接口。
  • 适配者类(Adaptee):现有接口,需要适配的类。
  • 适配器类(Adapter):实现目标接口,并通过适配者类完成目标接口所需的功能。

类图


代码示例

假设有一个音频播放器 AudioPlayer 只能播放 MP3 文件。为了支持播放更丰富的格式(如 MP4 和 VLC),我们使用适配器模式。

1. 目标接口

2. 适配者类

3. 适配器类

4. 客户端类


JDK 17 实现

在 JDK 17 中,可以使用**密封类(sealed class)**来定义 MediaPlayerAdvancedMediaPlayer,以明确限制允许的适配器类,确保设计的安全性。

JDK源码解析

Reader(字符流)、InputStream(字节流)的适配使用的是InputStreamReader。
InputStreamReader继承自java.io包中的Reader,对他中的抽象的未实现的方法给出实现。如:
如上代码中的sd(StreamDecoder类对象),在Sun的JDK实现中,实际的方法实现是对sun.nio.cs.StreamDecoder类的同名方法的调用封装。类结构图如下:
从上图可以看出:
  • InputStreamReader是对同样实现了Reader的StreamDecoder的封装。
  • StreamDecoder不是Java SE API中的内容,是Sun JDK给出的自身实现。但我们知道他们对构造方法中的字节流类(InputStream)进行封装,并通过该类进行了字节流和字符流之间的解码转换。
结论:
从表层来看,InputStreamReader做了InputStream字节流类到Reader字符流之间的转换。而从如上Sun JDK中的实现类关系结构中可以看出,是StreamDecoder的设计实现在实际上采用了适配器模式。

注意事项

  1. 兼容性问题:适配器模式主要是为了兼容不匹配的接口,但可能导致适配器类较多,增加维护难度。
  1. 接口稳定性:适配器的设计应尽量保证接口稳定,避免频繁修改目标接口。
  1. 性能问题:使用适配器可能会增加额外的调用层次,尤其在频繁调用的场景下,可能导致性能下降。

扩展

  1. 对象适配器与类适配器
      • 对象适配器:通过组合的方式持有适配者类的引用,适合需要适配多个类的情况。
      • 类适配器:通过继承适配者类实现适配,适合简单适配场景,但受限于 Java 单继承。
  1. 双向适配器:实现两种接口,使得两个不兼容的模块可以相互调用。例如,可以设计一个适配器同时实现 MediaPlayerAdvancedMediaPlayer,实现双向适配。
  1. 应用场景
      • 数据转换:如 XML 和 JSON 的相互适配。
      • 库或框架升级:通过适配器兼容新旧接口。
      • 系统集成:对接不同厂商的 API 接口。

小结

适配器模式通过一个中间类实现接口的转换和兼容,使得不同接口的类可以协同工作。在实际应用中,应根据需求选择合适的适配器类型(对象适配器或类适配器)。适配器模式虽然增加了系统灵活性,但也可能引入额外的复杂度,尤其是在适配器数量较多时,应注意代码维护性和性能问题。
上一篇
很鸡儿扯的报错
下一篇
说明

评论
Loading...