适配器模式适用的场景
适配器模式是一种常用的设计模式,能够将不兼容的接口转换为客户端所需的接口。在实际开发中,我们常常会遇到需要统一接口、替换外部系统、兼容旧接口或适配不同数据格式的情况。本文将结合详细的代码示例,介绍适配器模式的适用场景。
1. 统一多个类的接口设计
当一个功能的实现依赖于多个外部系统或类时,可以使用适配器模式将它们的接口适配为统一的接口定义。这样可以简化代码,使得调用者只需关注统一的接口。
示例:
// 统一接口
interface Payment {void pay(int amount);
}// 外部系统A
class Alipay {void makePayment(int amount) {System.out.println("Paid " + amount + " using Alipay.");}
}// 外部系统B
class WeChatPay {void payMoney(int amount) {System.out.println("Paid " + amount + " using WeChat Pay.");}
}// 适配器实现(针对 Alipay)
class AlipayAdapter implements Payment {private Alipay alipay;public AlipayAdapter(Alipay alipay) {this.alipay = alipay; // 将外部系统A注入适配器}@Overridepublic void pay(int amount) {alipay.makePayment(amount); // 调用外部系统A的方法}
}// 适配器实现(针对 WeChatPay)
class WeChatPayAdapter implements Payment {private WeChatPay weChatPay;public WeChatPayAdapter(WeChatPay weChatPay) {this.weChatPay = weChatPay; // 将外部系统B注入适配器}@Overridepublic void pay(int amount) {weChatPay.payMoney(amount); // 调用外部系统B的方法}
}
解释:
在这个示例中,Payment 接口是统一的支付接口,而 Alipay 和 WeChatPay 是两个不同的支付系统。通过 AlipayAdapter 和 WeChatPayAdapter,我们能够将这两个外部系统的接口适配为 Payment 接口,使得客户端只需调用 pay 方法即可。
2. 需要依赖外部系统时
当项目中依赖的外部系统需要替换时,利用适配器模式可以减少对代码的改动。这种方式让我们在替换外部系统时,只需更换适配器实现,而不需要修改客户端代码。
示例:
// 外部系统C
class PayPal {void executePayment(int amount) {System.out.println("Paid " + amount + " using PayPal.");}
}// 适配器实现
class PayPalAdapter implements Payment {private PayPal payPal;public PayPalAdapter(PayPal payPal) {this.payPal = payPal; // 将PayPal注入适配器}@Overridepublic void pay(int amount) {payPal.executePayment(amount); // 调用PayPal的方法}
}// 客户端代码
public class PaymentProcessor {private Payment payment;public PaymentProcessor(Payment payment) {this.payment = payment; // 注入适配器}public void processPayment(int amount) {payment.pay(amount); // 使用适配器进行支付}
}
解释:
在这个示例中,PaymentProcessor 类依赖于 Payment 接口,而不是直接依赖具体的支付实现。这样当我们想要替换支付系统(比如从 WeChatPay 替换为 PayPal)时,只需将相应的适配器传入 PaymentProcessor 的构造函数,而无需修改其内部逻辑。
3. 原有接口无法修改或功能过于老旧
在某些情况下,我们无法修改原有接口,或者原有接口的功能太老旧但又需要兼容。适配器模式可以帮助我们保留旧接口,并将其实现替换为更现代的接口。
示例:
// 老旧接口
interface OldList {void addElement(String element);
}// 新接口
interface NewList {void add(String item);
}// 新实现
class NewArrayList implements NewList {@Overridepublic void add(String item) {System.out.println("Added " + item + " to the new list.");}
}// 适配器实现
class OldListAdapter implements OldList {private NewList newList;public OldListAdapter(NewList newList) {this.newList = newList; // 将新接口注入适配器}@Overridepublic void addElement(String element) {newList.add(element); // 将老旧接口的方法调用转发到新接口}
}
解释:
在这个例子中,OldList 是一个过时的接口,而 NewList 是一个更新的接口。OldListAdapter 适配器通过将调用转发到 NewList 实现来实现兼容性,从而在使用旧接口的地方依然可以使用新功能。
4. 适配不同数据格式时
适配器模式在需要处理不同数据格式时特别有用。例如,Slf4j日志框架定义了打印日志的统一接口,并提供针对不同日志框架的适配器。
示例:
// 统一的日志接口
interface Logger {void log(String message);
}// 日志框架A
class Log4jLogger {void logMessage(String message) {System.out.println("Log4j: " + message);}
}// 日志框架B
class LogbackLogger {void writeLog(String message) {System.out.println("Logback: " + message);}
}// 适配器实现(针对 Log4j)
class Log4jAdapter implements Logger {private Log4jLogger log4jLogger;public Log4jAdapter(Log4jLogger log4jLogger) {this.log4jLogger = log4jLogger; // 将 Log4jLogger 注入适配器}@Overridepublic void log(String message) {log4jLogger.logMessage(message); // 调用 Log4j 的日志方法}
}// 适配器实现(针对 Logback)
class LogbackAdapter implements Logger {private LogbackLogger logbackLogger;public LogbackAdapter(LogbackLogger logbackLogger) {this.logbackLogger = logbackLogger; // 将 LogbackLogger 注入适配器}@Overridepublic void log(String message) {logbackLogger.writeLog(message); // 调用 Logback 的日志方法}
}
解释:
在这个例子中,Logger 是统一的日志接口,而 Log4jLogger 和 LogbackLogger 是两种不同的日志实现。通过 Log4jAdapter 和 LogbackAdapter,我们可以将这两个日志框架适配为统一的 Logger 接口,方便调用者在不关心底层实现的情况下进行日志记录。
总结
适配器模式的核心优势在于能够将不同接口之间的兼容性问题转化为更易处理的形式。通过上述四个场景的详细示例,我们可以看到适配器模式在开发中的广泛应用。不论是统一多个类的接口设计、替换外部系统、兼容老旧接口还是处理不同数据格式,适配器模式都能有效提高代码的灵活性与可维护性。希望这篇博客能够帮助你更好地理解适配器模式的应用!
相关文章:
适配器模式适用的场景
适配器模式是一种常用的设计模式,能够将不兼容的接口转换为客户端所需的接口。在实际开发中,我们常常会遇到需要统一接口、替换外部系统、兼容旧接口或适配不同数据格式的情况。本文将结合详细的代码示例,介绍适配器模式的适用场景。 1. 统一…...
Ambari里面添加hive组件
1.创建hive数据库 在添加hive组件之前需要做的事情,先在master这个虚拟机里面创建好hive 先进入虚拟机里面进入mysql 然后输入这个命令看看有没有自己创建的hive数据库 show databases;有的话会显示下面这个样子 没有的同学使用以下命令可以在MySQL中创建hive数…...
Windows部署rabbitmq
本次安装环境: 系统:Windows 11 软件建议版本: erlang OPT 26.0.2rabbitmq 3.12.4 一、下载 1.1 下载erlang 官网下载地址: 1.2 下载rabbitmq 官网下载地址: 建议使用解压版,安装版可能会在安装软件…...
【Flask】四、flask连接并操作数据库
目录 前言 一、 安装必要的库 二、配置数据库连接 三、定义模型 四、操作数据库 1.添加用户 2.删除用户 3.更新用户信息 4查询所有用户 五、测试结果 前言 在Flask框架中,数据库的操作是一个核心功能,它允许开发者与后端数据库进行交互…...
ES跟Kafka集成
配合流程 1. Kafka作为分布式流处理平台,能够实时收集和处理不同数据源的数据流; 2. 通过Kafka Connect或者Logstash等中间件,可以将Kafka中的数据流实时推送到Elasticsearch中; 3. Elasticsearch接收到数据后,会根据…...
Python Matplotlib:基本图表绘制指南
Python Matplotlib:基本图表绘制指南 Matplotlib 是 Python 中一个非常流行的绘图库,它以简单易用和功能丰富而闻名,适合各种场景的数据可视化需求。在数据分析和数据科学领域,Matplotlib 是我们展示数据的有力工具。本文将详细讲…...
供应商图纸外发:如何做到既安全又高效?
供应商跟合作伙伴、客户之间会涉及到图纸外发的场景,这是一个涉及数据安全、效率及合规性的重要环节。供应商图纸发送流程一般如下: 1.申请与审批 采购人员根据需要提出发放图纸的申请并提交审批; 采购部负责人审批发放申请,确…...
探索 Move 编程语言:智能合约开发的新纪元
目录 引言 一、变量的定义 二、整型 如何在Move中表示小数和负数? 三、运算符 as运算符 布尔型 地址类型 四、什么是包? 五、什么是模块? 六、如何定义方法? 方法访问权限控制 init方法 总结 引言 Move 是一种专为区…...
vue3+vant实现视频播放(含首次禁止进度条拖拽,视频看完后恢复,保存播放视频进度,刷新及下次进入继续播放,判断视频有无全部看完等)
1、效果图 2、 <div><videocontrolsclass"video_player"ref"videoPlayer":src"videoSrc"timeupdate"handleTimeUpdate"play"onPlay"pause"onPause"ended"onVideoEnded"></video><…...
情感强度分析:精确衡量文本情感强弱的 AI 技术
情感强度分析:精确衡量文本情感强弱的 AI 技术 一、引言 在当今信息爆炸的时代,我们每天都会接触到大量的文本信息。这些文本中蕴含着各种各样的情感,如喜悦、悲伤、愤怒、恐惧等。如何准确地理解和分析这些文本的情感强度,对于…...
工厂方法模式与抽象工厂模式
工厂方法模式 (Factory Method) 定义: 工厂方法模式是一种创建型设计模式,它定义了一个用于创建对象的接口,但让子类决定实例化哪个类。工厂方法将类的实例化推迟到子类。 优点: 解耦:客户端代码与具体的产品类解耦…...
「Math」初等数学知识点大纲(占位待处理)
✨博客主页何曾参静谧的博客📌文章专栏「C/C」C/C程序设计📚全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasoli…...
百元高性价比头戴式降噪耳机选哪款?四款平价性价比品牌别错过!
随着科技的发展,现在的头戴式耳机真的是越来越多样了,很多的朋友在选购耳机的时候,不知道哪一款头戴式耳机的性价比较高,究竟百元高性价比头戴式降噪耳机选哪款?身为一名数码爱好者,这里就给大家推带来四款…...
vue3 setup写不写到标签上的区别
在vue3种setup的写法,可以单独写setup()也可以写到script标签中,当然我们推荐后面这种 他的好处有很多,代码也简洁很多。1、属性和方法无需return,可直接使用 /*原先*/ <script> import { defineComponent } from "v…...
【论文解读】EdgeYOLO:一种边缘实时目标检测器(附论文地址)
论文地址:https://arxiv.org/pdf/2302.07483 这篇文章的标题是《EdgeYOLO: An Edge-Real-Time Object Detector》,由中国北京理工大学的Shihan Liu、Junlin Zha、Jian Sun、Zhuo Li和Gang Wang共同撰写。这篇论文提出了一个基于最新YOLO框架的高效、低复…...
xlwings,让excel飞起来!
excel已经成为必不可少的数据处理软件,几乎天天在用。python有很多支持操作excel的第三方库,xlwings是其中一个。 关于xlwings xlwings开源免费,能够非常方便的读写Excel文件中的数据,并且能够进行单元格格式的修改。 xlwings还…...
C语言学习,标准库 <stddef.h>
<stddef.h> C 标准库中头文件,它定义了一些常用的类型定义和宏。这些定义通常用于指针操作、数组处理和其他需要固定大小数据类型的场合。 size_t: 这是一个无符号整数类型,用于表示对象的大小(以字节为单位)。…...
PyQt5实战——操作台打印重定向,主界面以及stacklayout使用(四)
个人博客:苏三有春的博客 系类往期文章: PyQt5实战——多脚本集合包,前言与环境配置(一) PyQt5实战——多脚本集合包,UI以及工程布局(二) PyQt5实战——多脚本集合包,程序…...
React + Vite + TypeScript + React router项目搭建教程
一、创建项目 运行项目 二、目录结构 项目目录: ├─node_modules //第三方依赖 ├─public //静态资源(不参与打包) └─src├─assets //静态资源├─components //组件├─config //配置├─http //请求方法封装├─layout //页面…...
【ShuQiHere】️ 如何启用 SSH 服务
🛠️ 如何启用 SSH 服务 目录 基础概念 🌱检查是否已安装 SSH 服务 🔍在不同操作系统上安装 SSH 服务 💻 LinuxWindows 11macOS 启动和启用 SSH 服务 🚀配置防火墙以允许 SSH 连接 🔥配置 SSH 服务&#…...
测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...
大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
模型参数、模型存储精度、参数与显存
模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...
3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...
MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...
C++.OpenGL (20/64)混合(Blending)
混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...
2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)
安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...
