不得不说,在很多业务中,这种模式用得真的很香
故事“不能在写if else来拓展当前系统了,现在已经有三个支付场景了......”工位上,小猫看着电脑,挠着头。
就在刚刚,小猫接到了一个新需求,须要和客户公司买通资产,形成资产联动。说白了就是须要定制化对接客户公司的支付资产体系。除了这次接到的之外。前面其实已经对接了三家了。由于每家对接规范都不一样,历史对接的时候为了尽快上线,都是直接搞个else的新路由分支,然后去实现支付,退款。
在小猫看来,就是在堆屎山。牵一发而动全身的感觉真的很欠好。由于本次的需求留有的时间还是相当充裕的,所以小猫下定决心,计划利用这次的拓展,将原来不合理的地方用上设计模式将其重构掉。
深图远虑很久,小猫下定决心计划用“计谋模式”重构一番。
聊聊计谋模式
说到计谋模式,老猫觉得这种设计模式在现实开辟中利用其实是相当频仍的。老猫工作到现在也在很多业务场景中利用过如许的设计模式。例如,上述小猫碰到的第三方支付集成的问题上。别的的还有商城搞活动,针对不同的用户下单行为提供不同的折扣或者返现等活动。再例如商城运营人员根据不同的加价计谋去定在售商品的价格等。
老猫工作十年中,对接过很多外部企业或者单位的接口,若业务定义一样,只是接口协议不同的业务其实往往都可以用到计谋模式。
提炼一下适用场景如下:
(1)系统中有很多类,而它们的区别仅仅在于行为不同。
(2)一个系统须要动态地在几种算法中选择一种。
在很多业务中,这种模式用起来真的很香,既能够摆脱成堆的“if else”(当然关于 if else的优化,又是别的一个故事了,有兴趣的小伙伴可以看看这篇文章【接办了个项目,被if..else搞懵逼了】),别的写出来的代码本身拓展性也会比力好。
那么我们来看看计谋模式,并且基于小猫碰到的场景问题,咱们来撸一下实现代码。
计谋模式解决多路支付通道问题
在定义支付行为的时候,我们起首定义出通例的支付行为,咱们可以用接口interface的形式定义出来,当然也可以用abstract类的方式定义出来。这里老猫利用后者来定义。代码如下:
/**
* @author 公众号:程序员老猫
*/
public abstract class Payment {
//获取支付渠道的名称
public abstract String getName();
//查询用户余额
protected abstract BigDecimal queryBalance(String uid);
public PayState doPay(String uid, BigDecimal amount) {
if (queryBalance(uid).compareTo(amount) < 0) {
return new PayState(500, "支付失败", "账户余额不足");
}
return new PayState(200, "支付成功", "支付金额:" + amount);
}
}定义一个标准的支付状态类:
/**
* @author 公众号:程序员老猫
*/
public class PayState {
private int code;
private String msg;
private Object data;
public PayState(int code, String msg, Object data) {
this.code = code;
this.msg = msg;
this.data = data;
}
public String toString() {
return ("pay state :[" + code + "]," + msg + ",order detail: " + data);
}
}接下来,咱们来模仿各个支付渠道,并且咱们能够知道在不同的支付渠道中,我们当前的账户余额是多少。咱们就拿用的比力多的微信、支付宝、京东支付等支付渠道来做模仿吧。
支付宝实现,并且账户中有900元:
public class AliPay extends Payment {
@Override
public String getName() {
return "支付宝";
}
@Override
protected BigDecimal queryBalance(String uid) {
return new BigDecimal(900);
}
}微信支付,并且账户中有300元:
public class WxPay extends Payment{
@Override
public String getName() {
return "微信";
}
@Override
protected BigDecimal queryBalance(String uid) {
return new BigDecimal(300);
}
}以此类推,京东支付。
public class JDPay extends Payment{
@Override
public String getName() {
return "京东白条";
}
@Override
protected BigDecimal queryBalance(String uid) {
return new BigDecimal(400);
}
}定义好各种单一支付通道之后,其实我们就要组装计谋了。把上述支付通道,加载到计谋路由类中。老猫觉得这个地方也是计谋模式中比力核心的点。
/**
* @author 公众号:程序员老猫
*/
public class PayStrategy {
public static final String ALI_PAY = "aliPay";
public static final String WX_PAY = "wxPay";
public static final String JD_PAY = "jdPay";
public static final String DEFAULT = "wxPay";
//初始化的时候装载支付行为策略
private static Map<String,Payment> paymentMap = new HashMap<>();
static {
paymentMap.put(ALI_PAY,new AliPay());
paymentMap.put(WX_PAY,new WxPay());
paymentMap.put(JD_PAY,new JDPay());
paymentMap.put(DEFAULT,new WxPay());
}
//调用的时候路由具体的支付策略
public static Payment get(String payKey){
if(!paymentMap.containsKey(payKey)){
return paymentMap.get(DEFAULT);
}
return paymentMap.get(payKey);
}
}接下来,我们就模仿用户下订单支付行为了,具体如下:
/**
* @author 程序员老猫
* 下单场景
*/
public class Order {
private String uid; //用户Id
private String orderId; //订单Id
private BigDecimal orderAmount; //支付金额
public Order(String uid, String orderId, BigDecimal orderAmount) {
this.uid = uid;
this.orderId = orderId;
this.orderAmount = orderAmount;
}
public PayState doPay() {
return doPay(PayStrategy.DEFAULT);
}
public PayState doPay(String payKey) {
Payment payment = PayStrategy.get(payKey);
System.out.println("欢迎使用" + payment.getName());
System.out.println("本次交易金额:" + orderAmount);
return payment.doPay(uid, orderAmount);
}
}最终咱们来举行测试一下:
public class PayStrategyTest {
public static void main(String[] args) {
Order order = new Order("ktdaddy","20240425224901",new BigDecimal(245));
System.out.println(order.doPay(PayStrategy.ALI_PAY));
}
}结果输出:
欢迎使用支付宝
本次交易金额:245
pay state :,支付成功,order detail: 支付金额:245上述基本就是计谋模式的利用了。老猫觉得应该还是比力清晰的。咱们简单看一下最终的调用类图:
https://img2024.cnblogs.com/blog/2200669/202404/2200669-20240426092836455-595992620.png
到这里很多小伙伴可能会问了,上面写的案例其实并没有联合我们现实的spring开辟框架去实现计谋模式,日常开辟的过程中我们Java程序员主要用的还是spring框架。那么如果要联合咱们spring日常开辟框架又是怎么去实现呢。那么接下来,咱们接着往下看。
SpringBoot下计谋模式解决多路支付通道
其实核心的头脑还是上面这几个要领,老猫在此不多做展开,只是给大家提供一些思绪,然后提供一些简单的日常开辟中利用的截图给大家参考。支付利用计谋模式的核心的头脑无非就下面两个。
(1)咱们须要不同的支付计谋类。
(2)须要有路由支付计谋类的路由类。
其实上面两个核心中,比力重要的还是第二点,咱们如果去初始化计谋类。在上面案例中,老猫利用的静态方法块来装载各个计谋方法。在spring中其实我们可以利用@PostConstruct注解,举行service计谋的初始化装载。
如下起首定义一个标准的支付接口,并且实现一下:
public interface Payment {
//获取支付渠道的名称
String getCode();
PayState doPay(String uid, BigDecimal amount);
}然后实现这个接口,咱们举一个例子来说明
@Service
public class JDPay implements Payment {
@Override
public String getCode() {
return "jdPay";
}
@Override
public PayState doPay(String uid, BigDecimal amount) {
return null;
}
}关键此时咱们看一下核心加载的地方。
/**
* 程序员老猫
**/
@Service
public class PayStrategy {
@Autowired
private Payment[] payments;
//初始化的时候装载支付行为策略
private static Map<String, Payment> paymentMap = new ConcurrentHashMap<>();
@PostConstruct
private void initRouteMap() {
for (Payment externalPayService : payments) {
paymentMap.put(externalPayService.getCode(), externalPayService);
}
}
public Payment getPayment(String payCode) {
return paymentMap.get(payCode);
}
}上述就是联合spring的核心计谋模式的实现方式,老猫这里没有展开,但是最精华的部分,老猫觉得已经说清晰了。当然基于@PostConstruct举行计谋加载的方式只是一种。大家可以实现spring自带的InitializingBean,在 Spring 容器完成 bean 的属性注入后,会调用 afterPropertiesSet() 方法来执行初始化逻辑。
总结
上述主要和大家分享了基于计谋模式如何去做支付整合第三方支付的问题。当然这只是一个简单的案例,其实很多时候我们在现实的业务开辟中很多地方都可以用到如许一个模式。在jdk源码中以及spring源码中也屡见不鲜。但是计谋模式也不是万能的,存在优点的同时也存在缺点。
优点:
1、计谋模式符合开闭原则。(当然有兴趣相识设计原则的小伙伴接待戳【违反这些设计原则,系统就等着“腐烂”】)
2、计谋模式可以避免利用多重复的条件语句。例如优化if else。当然之前也老猫也写过类似博文。【接办了个项目,被if..else搞懵逼了】
3、利用计谋模式可以提高算法的保密性和安全性。
缺点:
1、不像适配器模式,计谋模式要求客户端须要知道全部的计谋,并且自行决定利用哪类计谋。关于适配器模式,感兴趣的小伙伴可以看这里【真香定律!我用这种模式重构了第三方登录】
2、计谋类会越来越多,维护资本也会越来越高。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]