当前位置: 首页 > news >正文

【设计模式】适配器模式 在java中的应用

文章目录

      • 适配器模式简介
        • 为什么需要适配器模式?
        • 类比
      • 适配器模式的结构与角色
        • 目标接口(Target)
        • 需要适配的类(Adaptee)
        • 适配器(Adapter)
        • 结构图示意
      • 适配器模式的实现方式
        • 类适配器实现(基于继承)
        • 对象适配器实现(基于组合)
      • 适配器模式的实际应用场景
        • 集成第三方库
        • 数据库驱动兼容
        • 旧系统迁移/升级
        • 前端开发中的兼容处理
        • JDK 中的应用
      • 适配器模式的优缺点分析
        • 优点
        • 缺点

适配器模式简介

适配器模式(Adapter Pattern),又称为包装器模式,是一种结构型设计模式。它的核心作用是**“将一个接口转换成客户希望的另一个接口”**,使原本因接口不兼容而无法工作的类可以协同工作。

为什么需要适配器模式?

在实际开发中,我们经常会遇到这样的问题:
我们手头有一个类A(比如老版本的接口),而现在需要用它来适配到一个新接口B(比如新系统的标准)。直接修改A的代码可能不现实(比如A是第三方库),这时候就可以用适配器模式来“桥接”它们。

类比

假设你买了一台美国进口的笔记本电脑,它的电源插头是美标的两扁头,而中国大陆的插座是国标的三孔插座。
你不能直接把美标插头插进国标插座,这时就需要一个插头转换器
插头转换器的作用就是:一边兼容美标插头,一边兼容国标插座,让两个本来“不兼容”的东西可以协同工作。

适配器模式的结构与角色

适配器模式的结构其实很简单,主要包括以下几个角色:

目标接口(Target)

这是客户端期待的接口,也就是系统希望使用的标准接口。
举例:你家里的国标插座就是目标接口。

package com.example.adapter;public interface Target {void request();
}

需要适配的类(Adaptee)

这个类是已经存在的,接口不兼容但功能可用。
举例:美标插头的设备就是 Adaptee。

package com.example.adapter;public class Adaptee {public void specificRequest() {System.out.println("Adaptee: 处理特殊请求");}
}

适配器(Adapter)

适配器是连接目标接口和需要适配的类的“桥梁”。
它实现了目标接口,并在内部持有 Adaptee 的引用,通过转换让二者协同工作。
举例:插头转换器就是 Adapter。

package com.example.adapter;// 对象适配器实现方式
public class Adapter implements Target {private Adaptee adaptee;public Adapter(Adaptee adaptee) {this.adaptee = adaptee;}@Overridepublic void request() {// 在这里做转换,让 Adaptee 能被 Target 使用adaptee.specificRequest();}
}

结构图示意
+-----------+         +------------+         +-----------+        +-----------+
|  Client   |  --->   |  Target    |  <---   | Adapter   |  --->  | Adaptee   |
+-----------+         +------------+         +-----------+        +-----------+
  • Client 通过 Target 接口调用 Adapter
  • Adapter 内部调用 Adaptee 的方法,实现接口转换

小结:
适配器模式的核心结构就是:目标接口(Target)+ 需要适配的类(Adaptee)+ 适配器(Adapter)
适配器实现了目标接口,并通过组合或继承的方式调用 Adaptee 的功能,实现接口的兼容。

适配器模式的实现方式

在 Java 中,适配器模式有两种常见实现方式:类适配器对象适配器
这两种方式本质上都是让“不兼容”的类能用统一的接口,但实现细节略有不同。


类适配器实现(基于继承)

类适配器通过继承需要适配的类(Adaptee),并实现目标接口(Target)。
由于 Java 只支持单继承,所以类适配器模式有一定局限性。

结构示意:

package com.example.adapter;// 目标接口
public interface Target {void request();
}// 需要适配的类
public class Adaptee {public void specificRequest() {System.out.println("Adaptee: 处理特殊请求");}
}// 类适配器
public class ClassAdapter extends Adaptee implements Target {@Overridepublic void request() {// 直接调用父类方法specificRequest();}
}

使用示例:

package com.example.adapter;public class AdapterDemo {public static void main(String[] args) {Target target = new ClassAdapter();target.request(); // 输出:Adaptee: 处理特殊请求}
}

特点:

  • 适配器通过继承 Adaptee 实现接口转换。
  • 只能适配一个类(受限于 Java 的单继承)。

对象适配器实现(基于组合)

对象适配器通过组合的方式,在适配器内部持有 Adaptee 的实例,并实现目标接口(Target)。

结构示意:

package com.example.adapter;// 目标接口
public interface Target {void request();
}// 需要适配的类
public class Adaptee {public void specificRequest() {System.out.println("Adaptee: 处理特殊请求");}
}// 对象适配器
public class ObjectAdapter implements Target {private Adaptee adaptee;public ObjectAdapter(Adaptee adaptee) {this.adaptee = adaptee;}@Overridepublic void request() {adaptee.specificRequest();}
}

使用示例:

package com.example.adapter;public class AdapterDemo {public static void main(String[] args) {Adaptee adaptee = new Adaptee();Target target = new ObjectAdapter(adaptee);target.request(); // 输出:Adaptee: 处理特殊请求}
}

特点:

  • 适配器通过组合 Adaptee 实例实现接口转换。
  • 可以适配多个类(更灵活,推荐使用)。

小结:

  • 类适配器:继承 Adaptee,适用于单继承场景,结构简单但灵活性较低。
  • 对象适配器:组合 Adaptee,更常用,灵活性高,推荐实际开发中优先选择。

适配器模式的实际应用场景

适配器模式在实际开发中非常常见,尤其是在系统集成、旧接口兼容、新旧系统迁移等场景。下面用具体例子和类比,帮助你理解适配器模式的实际应用。


集成第三方库

场景说明:
假设你在项目中需要用到一个第三方的日志库(如 Log4j),但你的系统统一使用了自定义的 Logger 接口。如果直接改动系统代码成本太高,可以为第三方库写一个适配器,让它实现你的 Logger 接口。

代码示例:

package com.example.adapter;// 系统要求的日志接口
public interface Logger {void log(String message);
}// 第三方日志库
import org.apache.log4j.Logger as Log4jLogger;public class Log4jAdapter implements Logger {private Log4jLogger log4jLogger;public Log4jAdapter(Log4jLogger log4jLogger) {this.log4jLogger = log4jLogger;}@Overridepublic void log(String message) {log4jLogger.info(message); // 转换到第三方库的方法}
}

数据库驱动兼容

场景说明:
假如你的系统原本用的是 MySQL 数据库,后来需要支持 PostgreSQL,但你的 DAO 层接口是统一的。可以写一个适配器,把 PostgreSQL 的驱动方法适配成你的 DAO 接口。


旧系统迁移/升级

场景说明:
公司老系统的接口和新系统不兼容,但又不能一下子全部重写。可以用适配器模式,将新系统的接口适配到老系统的实现,让二者能共同运行。


前端开发中的兼容处理

场景说明:
比如你用 Vue3 编写新组件,但项目里还有很多 Vue2 的代码,可以通过适配器模式包装 Vue2 组件,让它们可以在 Vue3 环境下运行。


JDK 中的应用

场景说明:
Java 标准库里也大量使用适配器模式。例如 java.io.InputStreamReader 适配了 InputStreamReader,让字节流可以作为字符流处理。

源码片段:

// InputStreamReader.java
public class InputStreamReader extends Reader {private final InputStream in;public int read(char[] cbuf, int offset, int length) throws IOException {// 实现将字节流转换为字符流}
}

适配器模式的优缺点分析

优点

提高代码复用性
可以复用已有的功能类(Adaptee),不需要修改原有代码,只需通过适配器进行接口转换。

增强系统灵活性和扩展性
适配器模式让系统能够兼容更多的第三方类或旧系统,便于后期扩展和集成。

解耦系统各模块
客户端只依赖目标接口(Target),不关心具体实现细节,有利于降低模块间耦合度。

满足“开放-封闭原则”
通过新增适配器类来适配不同接口,无需修改原有代码,符合 OCP 原则。


缺点

增加系统复杂度
引入适配器后,系统类的数量增加,结构变得更加复杂,理解和维护成本提升。

适配器编写成本
每当有新的 Adaptee 需要适配时,都要编写新的适配器类,增加开发工作量。

可能影响性能
适配器模式通常会增加一次方法调用(间接层),在高性能要求场景下可能略有影响。

只能适配“接口”不兼容,不能解决“业务”不兼容
适配器只能转换接口,无法解决业务逻辑上的差异,如果 Adaptee 的业务与 Target 差异过大,适配器模式就不适用了。

http://www.dtcms.com/a/392590.html

相关文章:

  • 2013/07 JLPT听力原文 问题四
  • MyBatis 缓存体系剖析
  • MySQL 主从复制 + MyCat 读写分离 — 原理详解与实战
  • Vmake AI:美图推出的AI电商商品图编辑器,快速生成AI时装模特和商品图
  • Debian13 钉钉无法打开问题解决
  • 02.容器架构
  • Diffusion Model与视频超分(1):解读淘宝开源的视频增强模型Vivid-VR
  • 通过提示词工程(Prompt Engineering)方法重新生成从Ollama下载的模型
  • 有没有可以检测反爬虫机制的工具?
  • 大模型为什么需要自注意力机制?
  • 长度为K子数组中的最大和-定长滑动窗口
  • Linux安装Kafka(无Zookeeper模式)保姆级教程,云服务器安装部署,Windows内存不够可以看看
  • WEEX编译|续写加密市场叙事
  • 为 Element UI 表格增添排序功能
  • 点评项目(Redis中间件)第四部分缓存常见问题
  • 动态水印也能去除?ProPainter一键视频抠图整合包下载
  • DevSecOps 意识不足会导致哪些问题
  • LeetCode:27.合并两个有序链表
  • 适用于双节锂电池的充电管理IC选型参考
  • 格式说明符
  • 层数最深叶子节点的和(深度优先搜索)
  • 【git】安装和基本指令
  • 如何利用AI技术快速生成专业级的PPT和视频内容
  • Linux系统之----线程互斥与同步
  • ARM SMMUv2架构下的安全和非安全状态(secure/non-secure)下的的资源分配解析
  • 面向linux新手的OrcaTerm AI 最佳实践
  • 构建高可用 LVS-DR + Keepalived 负载均衡集群实战指南
  • 网络协议总结
  • Python多线程爬虫加速电商数据采集
  • JVM之直接内存(Direct Memory)