实战运用模版方法+工厂方法+策略模式打造一套高扩展性的履约系统收单业务

在电商的业务中履约系统、支付系统往往都需要接好几个渠道的业务,如履约系统接收订单的时候,就要区分是充值订单、普通的履约单订单、普通的拆分商品的履约订单等等,不同的渠道业务会有不同的处理逻辑。下面使用模版方法和策略模式实现履约系统收取订单为案例来阐述他们如何让业务更清晰、代码更易维护的。下图是履约系统收单的流程图:

1、模版方法定义处理的公共逻辑

履约系统接收到订单消息之后,首先需要校验一下定时是否需要处理,如接入了三方的订单,此时就不需要我们自己的履约系统来处理。无论订单业务如何处理,第一步都是订单做验证,所以订单验证是一个固定的流程。那么我们可以将这个公共的业务流程设计成一个模版方法,伪代码如下所示:

public abstract class ReceiveOrderTemplate implements OrderStrategy { 
    public void receiveOrder(Integer orderType) { 
        //检测订单是否需要收单 
        if (!checkNeedReceiveOrder(orderType)) { 
            return; 
        } 
        //执行收单的逻辑 
        handlerOrder(orderType); 
    } 
    /** 
     * 检测订单的类型,判读是否收单 
     * 
     * @param orderType 订单的类型 
     */ 
    private boolean checkNeedReceiveOrder(Integer orderType){ 

        return true; 
    } 
}

上面就定义了一套模版方法,履约系统订单的收单逻辑都按照此方法定义的流程执行。这里把公共的订单校验的方法写成了私有方法,其目的就是保证模版方法被继承之后此方法不会被重写。

2、工厂方法决定执行策略

履约系统订单的收单有好几种策略,具体需要执行哪种策略需要我们自己定义,我们根据 orderTyp e (订单的类型)在工厂方法中返回具体的策略给上层,如下图所示:

工厂方法需要结合Spring相配合,将策略的方法交给spring管理,这样的话可以更加易于管理。

3、策略方式实现具体的业务逻辑

通过工厂方法找到具体的执行策略之后,就开始执行各自的实际业务逻辑,如下图所示:

将来如果要修改拆分策略我们只需要找到商品拆分订单业务逻辑这块做修改就可以了,这样也不会影响到其他的收单逻辑。如果增加了一个收单的逻辑的渠道(如虚拟订单收单策略),我们只需添加一个策略就可以快速实现收单渠道的接入。策略模式不仅使得业务清晰明了,而且对后续的维护工作也提供了极大的便利。

4、履约系统收单业务的落地实现

代码的包的规划如下所示:

策略类的实现:

public interface OrderStrategy { 
    /** 
     * 收单的类 
     *  
     * @param orderType 订单的类型 
     */ 
    void handlerOrder(Integer orderType); 
} 
---------------------------充值订单策略-------------------------------- 
@Component 
@Slf4j 
public class RechargeOrderStrategy extends ReceiveOrderTemplate { 

    @Override 
    public void handlerOrder(Integer orderType) { 
        System.out.println("充值订单收单了"); 
    } 
} 
---------------------------普通订单策略-------------------------------- 
@Component 
@Slf4j 
public class NormalOrderStrategy extends ReceiveOrderTemplate { 
    @Override 
    public void handlerOrder(Integer orderType) { 
        System.out.println("普通订单收单了"); 
    } 
} 
------------------------------拆分订单策略----------------------------- 
@Component 
@Slf4j 
public class SplitOrderStrategy extends ReceiveOrderTemplate { 
    @Override 
    public void handlerOrder(Integer orderType) { 
        System.out.println("拆分订单收单"); 
    } 
}

模版方法的实现:

public abstract class ReceiveOrderTemplate implements OrderStrategy { 
    public void receiveOrder(Integer orderType) { 
        //检测订单是否需要收单 
        boolean checkResult = checkNeedReceiveOrder(orderType); 
        if (!checkResult) { 
            return; 
        } 
        //执行收单的逻辑 
        handlerOrder(orderType); 
    } 
    /** 
     * 检测订单的类型,判读是否收单 
     *  
     * @param orderType 订单的类型 
     */ 
    private boolean checkNeedReceiveOrder(Integer orderType){ 
        //orderType == 0 表示是外部的订单 
        if(orderType == 0){ 
            return false; 
        } 
        return true; 
    } 
}

工厂方法的实现:

@Component 
@Slf4j 
public class ReceiveOrderFactory implements ApplicationContextAware { 
    private ApplicationContext applicationContext; 
    /** 
     * 根据订单的类型获取订单的执行策略 
     *  
     * @param orderType 订单的类型 
     */ 
    public ReceiveOrderTemplate getOrderStrategy(Integer orderType) { 
        switch (orderType){ 
            case 10: 
                return applicationContext.getBean(RechargeOrderStrategy.class); 
            case 20: 
                return applicationContext.getBean(NormalOrderStrategy.class); 
            case 30: 
                return applicationContext.getBean(SplitOrderStrategy.class); 
            default: 
                throw new RuntimeException("没有找到对应的策略"); 
        } 
    } 
    @Override 
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 
        this.applicationContext = applicationContext; 
    } 
}

测试类:

@RestController 
@RequestMapping("/order") 
public class ReceiveOrder { 
    @Resource 
    private ReceiveOrderFactory receiveOrderFactory; 
    @GetMapping("/get") 
    public String getOrder(Integer orderType){ 
        //获取执行的策略 
        ReceiveOrderTemplate orderStrategy = receiveOrderFactory.getOrderStrategy(orderType); 
        //执行收单的逻辑 
        orderStrategy.receiveOrder(orderType); 
        return "success"; 
    } 
}

效果:

至此我们完成了一套使用工厂方法+模版方法+策略模式实现了多渠道的收单业务。如果后续增加了收单的渠道,我们只需要增加收单策略和修改工厂方法获取策略就可以了,如下所示:

这样就可以在不影响其他的收单逻辑的情况下,快速接入新的功能。

0