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

适配器模式 java demo

适配器模式

适配器设计模式是一种结构设计模式,它通过将一个类的接口转换为客户端期望的另一个类来允许不兼容的接口协同工作。

它在以下情况下特别有用:
您正在与与当前界面不匹配的旧系统或第三方库集成。
您希望在不修改其源代码的情况下重用现有功能。
您需要弥合新旧代码之间的差距,或者使用不同接口设计构建的系统之间的差距。

当面对不兼容的接口时,开发人员通常会求助于重写大部分代码或嵌入条件,例如 处理特殊情况。例如,a 可以使用 逻辑来处理现代 和遗留。 if (legacyType)PaymentProcessorif-elseStripeServiceBankTransferAPI

但随着更多不兼容的服务或模块的引入,这种方法很快就会变得混乱、紧密耦合,并违反了开放/封闭原则——使系统难以扩展或重构。

适配器模式通过引入一个位于系统和不兼容组件之间的包装类来解决这个问题 。它将来自您界面的呼叫转换为旧系统或第三方系统可以理解的呼叫,而无需更改任何一端。

让我们通过一个真实世界的示例,看看如何应用适配器模式来无缝集成不兼容的组件并创建更灵活和可维护的架构。

问题:结账流程中的接口不兼容
想象一下,您正在构建电子商务应用程序的结账组件 。

您的结账服务旨在与支付接口配合使用来处理付款。

预期接口
以下是您 希望任何支付提供商遵守的合同:CheckoutService

public interface PaymentProcessor {void processPayment(double amount, String currency);boolean isPaymentSuccessful();String getTransactionId();
}

这种抽象使得在不改变任何核心业务逻辑的情况下交换支付提供商变得容易。

您的内部实施
您的团队已经有一个非常适合此界面的内部支付处理器:

public class InHousePaymentProcessor implements PaymentProcessor {private String transactionId;private boolean isPaymentSuccessful;@Overridepublic void processPayment(double amount, String currency) {System.out.println("InHousePaymentProcessor: Processing payment of " + amount + " " + currency);// Process payment logictransactionId = "TXN_" + System.currentTimeMillis();isPaymentSuccessful = true;System.out.println("InHousePaymentProcessor: Payment successful. Txn ID: " + this.transactionId);}@Overridepublic boolean isPaymentSuccessful() {return isPaymentSuccessful;}@Overridepublic String getTransactionId() {return transactionId;}
}

您 使用此界面并与内部支付处理器完美配合:CheckoutService

public class CheckoutService {private PaymentProcessor paymentProcessor;public CheckoutService(PaymentProcessor paymentProcessor) {this.paymentProcessor = paymentProcessor;}public void checkout(double amount, String currency) {System.out.println("CheckoutService: Attempting to process order for $" + amount + " " + currency);paymentProcessor.processPayment(amount, currency);if (paymentProcessor.isPaymentSuccessful()) {System.out.println("CheckoutService: Order successful! Transaction ID: " + paymentProcessor.getTransactionId());} else {System.out.println("CheckoutService: Order failed. Payment was not successful.");}}
}

以下是从您的主要电子商务应用程序调用它的方式:

public class ECommerceAppV1 {public static void main(String[] args) {PaymentProcessor processor = new InHousePaymentProcessor();CheckoutService checkout = new CheckoutService(processor);checkout.checkout(199.99, "USD");}
}

一切都很顺利。您已将结账业务逻辑与底层支付实现分离,从而实现未来的灵活性。到目前为止干得好。

现在,管理层提出了一个新要求:与传统第三方支付提供商集成,广泛使用并经过实战考验......但界面完全不同。

以下是该旧版支付类的样子:

public class LegacyGateway {private long transactionReference;private boolean isPaymentSuccessful;public void executeTransaction(double totalAmount, String currency) {System.out.println("LegacyGateway: Executing transaction for " + currency + " " + totalAmount);transactionReference = System.nanoTime();isPaymentSuccessful = true;System.out.println("LegacyGateway: Transaction executed successfully. Txn ID: " + transactionReference);}public boolean checkStatus(long transactionReference) {System.out.println("LegacyGateway: Checking status for ref: " + transactionReference);return isPaymentSuccessful;}public long getReferenceNumber() {return transactionReference;}
}

您现在有两个不兼容的接口。您现有 的期望是一个 .但 没有实现它,它的方法和签名不匹配:CheckoutServicePaymentProcessorLegacyGateway

processPayment(double)与。executeTransaction(double, String)

isPaymentSuccessful()与。checkStatus(long)

getTransactionId() vs. (而且它们的类型也不同!getReferenceNumber()

挑战是这样的:
你无法更改 ——它在系统范围内使用并与界面相关联 。CheckoutServicePaymentProcessor
您无法修改 — 它来自外部供应商。LegacyGateway
但你必须让它们一起工作。

您需要的是一个转换器——一个位于 和 之间的类 ,将不兼容的接口调整为适用于您的系统的接口。CheckoutServiceLegacyGateway

这正是适配器设计模式的作用。

适配器模式
适配器充当不兼容接口与客户端实际期望之间的桥梁。

它允许您的系统保持灵活性、可扩展性和解耦性,而无需修改现有的客户端代码或第三方库。

两种类型的适配器
实现适配器有两种主要方法,具体取决于语言和用例:

  1. 1. 对象适配器(Java 中的首选)
    使用组合:适配器保存对适配器(它包装的对象)的引用。
    允许跨类层次结构的灵活性和重用。
    这是 Java 中最常见和推荐的方法。
  2. 2. 类适配器(在 Java 中很少见)
    使用继承:适配器从目标接口和适配器继承。
    需要多重继承,Java 不支持类。
    更适合 C++ 等语言。

在我们的例子中,我们将使用 Object Adapter 模式来适应 接口。LegacyGatewayPaymentProcessor

类图

目标接口(例如,):客户端代码期望和使用的接口。PaymentProcessor

Adaptee(例如):具有不兼容接口的现有类,需要调整。LegacyGateway

适配器:实现 Target 接口并在内部使用 Adaptee 的类。它将 Target 接口上的调用转换为 Adaptee 接口上的调用。

客户端(例如,):系统中使用 Target 接口的部分。CheckoutService

现实世界的类比
想象一下,您正在从美国前往欧洲。您的笔记本电脑充电器使用 A 型插头(在美国使用),但欧洲墙壁插座需要 C 型插头。

您无法直接插入充电器 - 接口不匹配。

您无需购买新充电器,而是使用旅行插头适配器。该设备接受您的 A 型插头并将其转换为适合欧洲插座的 C 型形状。

您不会修改墙上插座(它类似于第三方 API)。
您无需修改充电器(这就像您现有的业务逻辑)。
适配器位于中间并转换连接。

对于我们的示例:
充电器→您的应用 (CheckoutService)
墙壁插座→第三方系统(LegacyGateway)
旅行插头适配器 → 适配器等级 (LegacyGatewayAdapter)

您的应用程序需要一个接口 (),但旧系统提供了另一个接口 ()。该适配器允许两者协同工作,而无需改变任何一侧。PaymentProcessorLegacyGateway

实现适配器
为了将旧类集成 到我们的现代电子商务系统中,我们将创建一个 名为 的对象适配器。LegacyGatewayLegacyGatewayAdapter

这个适配器将实现 我们 已经依赖的接口。在内部,它会将方法调用转换为适当的作, 从而有效地弥合不兼容 API 之间的差距。PaymentProcessorCheckoutServiceLegacyGateway

适配器实现

public class LegacyGatewayAdapter implements PaymentProcessor {private LegacyGateway legacyGateway;public LegacyGatewayAdapter(LegacyGateway legacyGateway) {this.legacyGateway = legacyGateway;}@Overridepublic void processPayment(double amount, String currency) {System.out.println("LegacyGatewayAdapter: Processing payment of " + amount + " " + currency);legacyGateway.executeTransaction(amount, currency);System.out.println("LegacyGatewayAdapter: Payment processed successfully. Txn ID: " + legacyGateway.getReferenceNumber());}@Overridepublic boolean isPaymentSuccessful() {return legacyGateway.checkStatus(legacyGateway.getReferenceNumber());}@Overridepublic String getTransactionId() {return String.valueOf(legacyGateway.getReferenceNumber());}
}

客户端代码保持不变
适配器模式的美妙之处在于,您的客户端代码仍然完全不知道旧版集成。

不 在乎它是处理现代付款还是传统付款,它总是与 .CheckoutServicePaymentProcessor

更新后的客户端代码如下所示:

public class ECommerceAppV2 {public static void main(String[] args) {PaymentProcessor inHouseProcessor = new InHousePaymentProcessor();PaymentProcessor legacyProcessor = new LegacyGatewayAdapter(new LegacyGateway());CheckoutService checkoutService = new CheckoutService(inHouseProcessor);checkoutService.checkout(100, "USD");System.out.println("--------------------------------");checkoutService = new CheckoutService(legacyProcessor);checkoutService.checkout(100, "USD");}
}

是什么让这个适配器工作?
组合胜过继承
我们使用对象组合,而不是继承。适配器包装而不是 子类化它。这使适配器保持:LegacyGateway

松散耦合
更易于测试
更灵活地改变

它还遵循有效的 Java 最佳实践来处理第三方或遗留代码。

方法翻译
中的每个方法 都转换为对旧版 API 的等效调用。这通常包括:PaymentProcessor

重命名或重新映射方法名称
重新组织参数
转换返回类型 — 例如,将 事务引用转换为格式化 的 IDlongString

旧逻辑的封装
适配器保护代码库的其余部分免受旧类的怪癖或结构的影响。从外部看,没有人知道或关心遗留系统正在被使用。

这改进了:
封装
代码可读性
可维护性

其他阅读材料:

https://pan.baidu.com/s/1c1oQItiA7nZxz8Rnl3STpw?pwd=yftc
https://pan.quark.cn/s/dec9e4868381

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

相关文章:

  • 电能质量监测装置 分布式光伏安全并网“准入证”
  • AI工作负载“加速跑”,高性能网络如何“护航”?
  • EfficientVMamba代码略讲
  • 档案宝系统功能:权限分级,保障档案安全
  • KingbaseES数据库增删改查操作分享
  • 项目集成 Chrono 时间轴
  • Pytest 插件怎么写:从0开发一个你自己的插件
  • SamOutVXP: 轻量级高效语言模型
  • 用nohup setsid绕过超时断连,稳定反弹Shell
  • Spring 循环依赖:从 “死锁” 到 “破局” 的完整解析
  • 在.NET 8 中使用中介模式优雅处理多版本 API 请求
  • 大数据毕业设计选题推荐-基于大数据的鲍鱼多重生理特征数据可视化分析系统-Spark-Hadoop-Bigdata
  • AUTOSAR自适应平台(AP)中元类(Metaclass)、建模(Modeling) 和 ARXML 这三者的核心关系与区别
  • 阿里云上部署nuxt开发的项目(SSG和SSR混合渲染)
  • Qwen2-阿里云最新发布的通义千问开源大模型
  • AR眼镜在制造业的生产设备智慧运维方案介绍
  • CRMEB私域电商系统后台开发实战:小程序配置全流程解析
  • Unity 二进制读写小框架
  • 机器人 - 无人机基础(4) - FreeRTOS
  • MFC随笔—不使用对话框资源模板创建对话框
  • 嵌入式ARM程序高级调试基础:8.QEMU ARM虚拟机与tftp配置
  • QT的项目pro qmake编译
  • OpenCV结构光三维重建类cv::structured_light::GrayCodePattern
  • 01 网络信息内容安全--绪论
  • OpenCV图像色彩空间转换
  • OpenCV图像形态学操作
  • SigNoz 外置 ClickHouse 高可用部署实践
  • Qt二维码生成器项目开发教程 - 从零开始构建专业级QR码生成工具
  • AI + 云原生 + ITSM 的三重融合:企业数字化转型的新引擎
  • Azure官网为何没直接体现专业服务