综合技术

策略模式实践

微信扫一扫,分享到朋友圈

策略模式实践
0

模式简介

策略模式是一种行为型模式,它定义一系列的算法,将每一种算法封装起来并可以相互替换使用,策略模式让算法独立于使用它的客户端应用而独立变化。 策略模式适合解决当程序出现多个不同分支,而且每个分支的逻辑还比较复杂的场景。

需求分析

在笔者参与的交易系统中,需要支持多种支付方式,如支付宝、微信、现金、银行卡等等,每一种支付方式的处理逻辑都不尽相同,对接的系统也不一样,所以程序中需要根据用户选择的支付方式来确定走哪一种支付方式的流程,根据需求描述就能看出,很适合用策略模式来解决这个问题,每一种支付方式就是一个策略,每个策略封装自己的支付逻辑。

详细设计

我们来看设计类图:

简单介绍一下逻辑:

  • PayHandler 的 pay 方法处理整体的支付逻辑

  • 首先构建 PayStrategyContext 上下文对象,构建完成后,上下文会包含支付单、支付明细、抹零模型、支付请求等对象

  • 上下文对象本身会作为参数传递后面的具体支付策略中,图中只列出了两个具体的策略,支付宝支付和微信支付

  • 支付策略 PayStrategy 接口包含两个方法,一个是用于完成支付动作的 pay 方法,另一个是用来匹配支付方式的 support 的方法

  • PayHandler 会根据用户选择的支付方式调用 selectStrategy 方法在内部维护的 PayStrategy 集合中选择出匹配的策略设置到 PayStrategyContext 中并调用 PayStrategyContext 的 pay 方法完成支付操作

  • 在完成支付后,将支付结果的一些信息更新到支付单中,并发送支付结果消息

代码实现

下面我们来看代码实现:

/**
 * 支付策略
 */
public interface PayStrategy {

    /**
     * 支付
     */
    void pay(PayStrategyContext context);

    /**
     * 匹配支付方式
     */
    boolean support(String payType);

}
/**
 * 支付策略环境
 */
@Slf4j
public class PayStrategyContext {

    @Getter
    private PayRecord pay;

    @Getter
    private PayDetail detail;
    
    @Getter
    private PayDetail cutDetail;
    
    @Getter
    private PayRequest payRequest;
    
    private PayStrategy strategy;

    public PayStrategyContext(PayRecord pay, PayDetail detail, PayRequest payRequest) {
        this.pay = pay;
        this.detail = detail;
        this.payRequest = payRequest;
        this.cutDetail = ...;
        // ...
    }

    public PayStrategyContext setStrategy(PayStrategy strategy) {
        this.strategy = strategy;
        return this;
    }

    public void pay() {
        strategy.pay(this);
    }

}
/**
 * 支付平台支付策略
 */
@Slf4j
@Service
public class AlipayPayStrategy implements PayStrategy {
    @Override
    public boolean support(String payType) {
        return "Alipay".equals(payType);
    }

    @Override
    public void pay(PayStrategyContext context) {
        // 调用支付宝服务...
        // ...
    }
}
/**
 * 微信支付策略
 */
@Slf4j
@Service
public class MybankPayStrategy implements PayStrategy {
    @Override
    public void pay(PayStrategyContext context) {
        // 对接微信支付服务...
        // ...
    }

    @Override
    public boolean support(String payType) {
        return "WechatPay".equals(payType);
    }
}
/**
 * 支付处理
 */
@Slf4j
@Service
public class PayHandler {

    @Resource
    private List<PayStrategy> payStrategyList;

    /**
     * 支付
     */
    public PayResponse pay(long payId, PayRequest request) {
        PayRecord pay = fromDB(payId);
        for (PayDetail detail : pay.getDetails()) {
            new PayStrategyContext(pay, detail, request)
                .setStrategy(selectPayStrategy(detail.getPayType()))
                .pay();
        }
        update(pay, pay.getDetails());
        sendMessages(buildMessages(pay));
        return buildResponse(pay, request);
    }

    /**
     * 根据支付方式选择支付策略
     */
    private PayStrategy selectPayStrategy(String payType) {
        return payStrategyList.stream()
            .filter(s -> s.support(payType))
            .findAny()
            .orElseThrow(() -> new RuntimeException("支付方式不支持"));
    }

    /**
     * 构建支付消息
     */
    private List<Message> buildMessages(PayRecord pay) {
        List<Message> list = Lists.newArrayList();
        // 构建消息
        return list;
    }

    /**
     * 支付后更新支付信息
     */
    private void update(Payrecord pay, List<PayDetail> details) {
        // DB更新
    }

}

总结

这种设计的好处在于我们统一了所有支付方式的支付流程,由 PayHandler 进行封装和处理,而每个支付方式之间不同的逻辑由具体的策略类来实现,中间由 context 环境类进行交互,这样后续再扩展其他支付方式时,不会影响其他支付方式,也不需要修改原来的支付流程,整体扩展性很好,维护起来也比较方便。

本文受原创保护,未经作者授权,禁止转载。 linkedkeeper.com (文/张强)

阅读原文...

微信扫一扫,分享到朋友圈

策略模式实践
0
LinkedKeeper

Creating a custom kubectl plugin to connect to SQL Server in Kubernetes

上一篇

contextvars模块到底是做什么的?

下一篇

评论已经被关闭。

插入图片

热门分类

往期推荐

策略模式实践

长按储存图像,分享给朋友