允许个人做动漫网站吗,seo搜索引擎优化服务,不备案域名能用吗,贵司不断优化网站建设一、引言
对于包含支付功能的项目#xff0c;在项目初期#xff0c;我们常常为了快速上线#xff0c;会简单粗暴的写出这样的代码#xff1a;
public String pay(String paymentType, Order order) {if (alipay.equals(paymentType)) {// 调用支付宝} else i…一、引言对于包含支付功能的项目在项目初期我们常常为了快速上线会简单粗暴的写出这样的代码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 MapString,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块支付逻辑分散到各个策略类中职责单一。实现了开闭原则未来要新增新的支付只需新建类文件无需修改任何现有工厂和服务的代码。代码更加优雅和健壮易于维护和单元测试。