news 2026/4/18 3:43:09

用Spring Boot+工厂+策略模式优雅解耦支付系统

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用Spring Boot+工厂+策略模式优雅解耦支付系统

一、引言

对于包含支付功能的项目,在项目初期,我们常常为了快速上线,会简单粗暴的写出这样的代码:

public String pay(String paymentType, Order order) { if ("alipay".equals(paymentType)) { // 调用支付宝 } else if ("wechat_pay".equals(paymentType)) { // 调用微信 } else if ("union_pay".equals(paymentType)) { // 银联支付处理... } // ... 更多的else if else { throw new RuntimeException("不支持的支付方式!"); } }

起初,这段代码工作的很好。但随着业务飞速发展,支付方式越来越多,这个pay方法就像一块磁铁,吸引着所有的变动和风险,逐渐变的难以维护。每一次新增或修改支付方式,都像是在这坨已经混乱不堪的“屎山”上再小心翼翼地垒上一块砖,令人心惊胆战。

本文将带你运用工厂模式与策略模式这两种设计模式,对支付系统进行一次彻底的重构。实现将一团乱麻的支付逻辑梳理成一个个职责单一的独立模块,最终实现优雅、健壮、易于扩展的支付功能。

二、设计模式介绍(工厂、策略)

1. 策略模式(Strategy)

定义多个算法(支付方式),封装每一个算法,并使它们可以互相替换,让算法的变化独立于使用的客户端。简单来说,就是我们先定义好不同支付方式的实现,并将这些实现分别封装在独立的类中,在运行期间根据具体的需要选择不同的实现即可。

2. 工厂模式(Factory)

负责创建策略对象(支付方式)的复杂过程,客户端无需关心具体的实现类。简单来说,就是将具体支付方式的对象交给工厂来创建。打个比方:现在有三种支付策略,分别是微信支付、支付宝支付、银联支付,如果用户希望使用微信支付,只需要告诉工厂,工厂就会自动创建微信支付策略的对象返回给用户,用户拿到对象后直接使用即可。

看到这里,有些小伙伴可能会觉得工厂模式有点多余:用户为什么不直接创建具体的策略,而是通过工厂去创建呢?有什么区别呢?

3. 抽象工厂+策略模式

到目前为止,一共有三种支付方式,但是要知道,这三种支付方式分别隶属不同的供应商,并且这三种支付方式下,还存在更具体的支付方式。比如微信支付,包含微信扫描支付、微信H5支付、微信APP支付,其他支付方式也是这样。所以对于微信支付,应该将它看做是一个产品类,产品类下面包含了很多产品,这些具体的产品才是真正具体的支付方式。刚才还说到过,这些产品类分别隶属于不同的供应商,所以我们可以把这些供应商看做是不同的工厂。它们之间的关系如下图所示:

上图所展示的是工厂+策略模式实现支付的完整形态,到这里,工厂模式已经不是简单的工厂,而是抽象工厂,所以最终我们我要实现的支付方案就是:抽象工厂模式+策略模式 !

三、 实战:三步构建支付系统

  • 第一步:定义支付策略
  • 第二步:创建工厂类,管理所有策略
  • 第三步:编写工具类,优雅调用

1. 定义支付策略(模拟支付)

分别定义微信、支付宝、银联的支付策略,每个类中的方法表示一个独立的支付策略。

/** * 支付宝支付策略 */ public class AlipayStrategy{ public ResponseEntity h5Pay(OrderInfo orderInfo) { // 调用支付宝SDK的具体逻辑... String data = "使用支付宝H5支付:订单号=" + orderInfo.getOrderId() + ", 金额=" + orderInfo.getAmount(); return ResponseEntity.ok(data); } public ResponseEntity appPay(OrderInfo orderInfo){ // 调用支付宝SDK的具体逻辑... String data = "使用支付宝APP支付:订单号=" + orderInfo.getOrderId() + ", 金额=" + orderInfo.getAmount(); return ResponseEntity.ok(data); } } /** * 银联支付策略 */ public class UnionPayStrategy { public ResponseEntity aggrPay(OrderInfo orderInfo){ String data = "使用银联聚合支付:订单号=" + orderInfo.getOrderId() + ", 金额=" + orderInfo.getAmount(); return ResponseEntity.ok(data); } public ResponseEntity PCPay(OrderInfo orderInfo){ String data = "使用银联PC支付:订单号=" + orderInfo.getOrderId() + ", 金额=" + orderInfo.getAmount(); return ResponseEntity.ok(data); } } /** * 微信支付策略 */ public class WeChatPayStrategy { public ResponseEntity scanPay(OrderInfo orderInfo){ String data = "使用微信扫描二维码支付:订单号=" + orderInfo.getOrderId() + ", 金额=" + orderInfo.getAmount(); return ResponseEntity.ok(data); } }

2. 创建工厂类,管理所有策略

先定义一个抽象工厂类,包含一个抽象方法,用来获取支付产品类。

/** * 支付服务商抽象类 */ public abstract class SupplierFactory { /** * 获取支付产品类 * @return */ public abstract PayProduct getProduct(); }

再定义表示三个支付服务商的具体工厂,用来获取具体的支付产品类

/** * 支付宝服务商工厂 */ public class AlipayFactory extends SupplierFactory{ //获取支付宝产品类 @Override public PayProduct getProduct() { return new AlipayPayProduct(); } } /** * 银联服务商工厂 */ public class UnionPayFactory extends SupplierFactory{ //获取银联产品类 @Override public PayProduct getProduct() { return new UnionPayProduct(); } } /** * 微信服务商工厂 */ public class WeChatFactory extends SupplierFactory{ //获取微信产品类 @Override public PayProduct getProduct() { return new WeChatPayProduct(); } }

现在已经定义好了生产支付产品的工厂,接下来就要创建具体的支付产品了。首先要定义一个产品类接口,再分别创建表示微信支付产品、银联支付产品、支付宝支付产品的实现类。

/** * 支付产品类接口 */ public interface PayProduct { /** * 获取支付策略实现类 * @return */ <T> T getPayStrategy(); } /** * 支付宝支付产品类 */ public class AlipayPayProduct implements PayProduct{ //获取支付宝支付策略对象 @Override public AlipayStrategy getPayStrategy() { return new AlipayStrategy(); } } /** * 银联支付产品类 */ public class UnionPayProduct implements PayProduct{ //获取银联支付策略对象 @Override public UnionPayStrategy getPayStrategy() { return new UnionPayStrategy(); } } /** * 微信支付产品类 */ public class WeChatPayProduct implements PayProduct{ //获取微信支付策略对象 @Override public WeChatPayStrategy getPayStrategy() { return new WeChatPayStrategy(); } }

至此,就已经创建完了工厂模式+策略模式的支付设计。现在还需要一个工具类,去完成支付的调用,在这以前,先创建一个订单实体类和请求实体类用于后续测试支付。

//订单实体类 @Data public class OrderInfo { private Long orderId; private String orderName; private BigDecimal amount; } //支付请求体 @Data public class OrderPayDTO { private String method; private String payMethod; private OrderInfo orderInfo; }

3. 编写工具类,优雅调用

/** * 获取具体工厂工具类 */ public class PayUtils { static final Map<String,SupplierFactory> supplierFactorys = new HashMap<>(); static { supplierFactorys.put("WeChat",new WeChatFactory()); supplierFactorys.put("Alipay",new AlipayFactory()); supplierFactorys.put("Union",new UnionPayFactory()); } /** * 统一支付方法 * @param orderPayDTO * @return * @throws NoSuchMethodException * @throws InvocationTargetException * @throws IllegalAccessException */ public static Object pay(OrderPayDTO orderPayDTO) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { SupplierFactory supplierFactory = supplierFactorys.get(orderPayDTO.getMethod()); PayProduct product = supplierFactory.getProduct(); Object payStrategy = product.getPayStrategy(); Class<?> clazz = payStrategy.getClass(); Method declaredMethod = clazz.getDeclaredMethod(orderPayDTO.getPayMethod(), OrderInfo.class); return declaredMethod.invoke(payStrategy,orderPayDTO.getOrderInfo()); } }
  • supplierFactorys:存储所有的支付服务商名称(在业务系统中,这些数据应该从数据库中读取)。
  • supplierFactorys.get(orderPayDTO.getMethod()):根据用户选择的支付方式数据获取具体的支付服务商工厂对象。
  • supplierFactory.getProduct():从工厂中创建产品类对象,如支付宝支付产品类、微信支付产品类。
  • product.getPayStrategy():获取支付策略对象。
  • 最后根据用户从前端传递的支付方法名(在支付方式管理功能中,可以提前将此信息设置到支付方式表信息的字段中),利用反射机制避免大量的if-else代码,调用具体的策略方法完成支付。

四、支付功能测试

1. 编写controller层支付测试接口

@RestController public class PayController { /** * 支付接口 * @param orderPayDTO * @return */ @PostMapping("/pay") public ResponseEntity pay(@RequestBody OrderPayDTO orderPayDTO) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException { /** 其他业务代码,比如获取请求参数,获取订单信息等 */ return (ResponseEntity)PayUtils.pay(orderPayDTO); } }

2. 使用Postman测试支付接口

2.1 微信扫码支付

2.2 支付宝H5支付

2.3 银联聚合支付

五、总结

通过以上四步,我们成功地:

  • 消除了庞大的if-else块,支付逻辑分散到各个策略类中,职责单一。
  • 实现了开闭原则:未来要新增新的支付,只需新建类文件,无需修改任何现有工厂和服务的代码。
  • 代码更加优雅和健壮,易于维护和单元测试。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/17 21:10:21

HTML meta标签优化提升GLM技术博客SEO排名

HTML Meta标签优化与GLM-4.6V-Flash-WEB模型的技术协同&#xff1a;提升AI内容传播效率 在人工智能技术加速落地的今天&#xff0c;一个尖锐的问题日益凸显&#xff1a;再先进的模型&#xff0c;如果开发者找不到、看不懂、用不起来&#xff0c;它的价值就大打折扣。 以智谱AI最…

作者头像 李华
网站建设 2026/4/8 14:45:30

PyCharm模板代码提升GLM-4.6V-Flash-WEB开发效率

PyCharm模板代码提升GLM-4.6V-Flash-WEB开发效率 在当今快速迭代的AI应用开发中&#xff0c;一个常见的痛点浮出水面&#xff1a;即便有了强大的模型&#xff0c;开发者仍需反复编写相似的加载逻辑、预处理流程和接口封装代码。特别是在Web端部署多模态大模型时&#xff0c;从本…

作者头像 李华
网站建设 2026/4/14 8:26:03

CSDN官网收藏夹整理GLM-4.6V-Flash-WEB学习资料

GLM-4.6V-Flash-WEB&#xff1a;轻量级多模态模型的落地实践 在今天这个图像与文本交织的信息时代&#xff0c;用户早已不再满足于“上传图片、返回标签”式的简单交互。无论是电商平台中自动解析商品截图的价格信息&#xff0c;还是教育场景下对图表题目的智能讲解&#xff0c…

作者头像 李华
网站建设 2026/4/15 14:45:48

Dify响应类型配置实战解析(仅限高级用户的核心秘籍)

第一章&#xff1a;Dify响应类型配置的核心概念在构建基于Dify平台的AI应用时&#xff0c;响应类型配置是决定模型输出行为的关键环节。合理的配置不仅能提升用户体验&#xff0c;还能确保系统与前端或其他服务之间的数据交互更加高效和规范。响应类型的定义与作用 响应类型用于…

作者头像 李华
网站建设 2026/4/11 19:08:01

Vue-springboot医院挂号管理系统4n9w0

目录系统概述核心功能技术亮点应用价值开发技术核心代码参考示例1.建立用户稀疏矩阵&#xff0c;用于用户相似度计算【相似度矩阵】2.计算目标用户与其他用户的相似度总结源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;系统概述 Vue-S…

作者头像 李华
网站建设 2026/4/15 2:27:48

Vue-springboot心理健康咨询与诊断平台设计与实现

目录 Vue-SpringBoot心理健康咨询与诊断平台设计与实现摘要 开发技术 核心代码参考示例1.建立用户稀疏矩阵&#xff0c;用于用户相似度计算【相似度矩阵】2.计算目标用户与其他用户的相似度总结源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#…

作者头像 李华