责任链模式实践

坏味道代码

最近在开发过程中需要修改这样一段代码:

InvoiceSubmitter invoiceSubmitter;
if (isBizBook) { // 图书业务
    if (isVatInvoice) { // 增值税专用发票
        invoiceSubmitter = rjVatInvoiceSubmitter;
    } else { // 增值税普通发票
        invoiceSubmitter = rjGeneralInvoiceSubmitter;
	}
} else {
    invoiceSubmitter = commonInvoiceSubmitter; // 通用发票申请
}
invoiceSubmitter.submitRequisition(order); 

关于InvoiceSubmitter类图如下:
这里写图片描述
OrderFinishSupport直接关联InvoiceSubmitter接口,AbstractInvoiceSubmitter实现InvoiceSubmitter接口的submitRequisition方法封装通用逻辑,并定义另外一个重载的submitRequisition方法供子类实现具体业务逻辑。

业务逻辑

这是一段发票提交的逻辑,在我们系统的订单完成之后,需要根据用户提交的发票内容调用不同的接口将发票信息提交到发票系统,发票系统来完成为用户开具发票的工作。

这段代码目前看起来还算清晰,就是根据业务和发票的类型判断调用哪个接口,但是这次需要修改这段代码,加上分支判断逻辑区分另外一种业务,未来还会承接更多的需求,这样这段代码的条件分支判断会越来越庞大,可读性会越来越差,也越来越难维护。

具体设计

重构开始,这段逻辑整体看起来就是一条链,每个submitter处理满足自己条件的请求,所以责任链模式可以很好的解决这个问题,重构之后结构如下:
这里写图片描述
抽象InvoiceSubmitHandler,OrderFinishSupport改为关联InvoiceSubmitHandler,在InvoiceSubmitHandler的初始化方法init中调用各个submitter的setNextHandler方法构建好整个责任链,每个具体的submitter通过match方法返回自己是否能够处理本次请求的波尔值,AbstractInvoiceSubmitter会根据这个返回值判断用当前的submitter处理还是调用下一个nextHandler来处理。

代码实现

关键代码如下:

class InvoiceSubmitHandler {

    private InvoiceSubmitter commonInvoiceSubmitter;

    private InvoiceSubmitter rjGeneralInvoiceSubmitter;

    private InvoiceSubmitter rjVatInvoiceSubmitter;

    /**
     * 初始化链条,设置handler的下一个handler
     */
    public void init() {
        commonInvoiceSubmitter.setNextHandler(rjGeneralInvoiceSubmitter);
        rjGeneralInvoiceSubmitter.setNextHandler(rjVatInvoiceSubmitter);
    }

    /**
     * 提交发票申请单
     */
    public void submitRequisition() {
        commonInvoiceSubmitter.submitRequisition();
    }

}

abstract class AbstractInvoiceSubmitter implements InvoiceSubmitter {


    /**
     * 下一个handler
     */
    private InvoiceSubmitter nextHandler;


    /**
     * 提交申请单
     */
    public void submitRequisition() {
        if (match()) {
            submitRequisition();
            return;
        }
        if (nextHandler == null) {
            return; // 如果下一个handler为空,证明当前handler已经是最后一个handler,直接返回,证明本次请求不需要处理
        }
        nextHandler.submitRequisition();
    }

    /**
     * 判断当前handler是否能够处理当前请求
     */
    protected abstract boolean match();

    /**
     * 设置下一个handler
     */
    public void setNextHandler(InvoiceSubmitter handler) {
        this.nextHandler = handler;
    }


    /**
     * 子类具体实现提交发票申请单逻辑
     */
    protected abstract void submitRequisition();

}

class RJGeneralInvoiceSubmitter extends AbstractInvoiceSubmitter {

    /**
     * 判断当前handler是否能够处理当前请求
     */
    protected boolean match() {
        return 是图书业务 && 发票类型为增值税普通发票;
    }

    /**
     * 提交申请单
     */
    public void submitRequisition() {
        ...
    }
}

具体submitter只列出一个,其他类似。

总结

重构之后,具体的匹配逻辑分散到各个子类中实现,类的职责更加明确和集中,代码可读性、扩展性更好。在使用责任链模式的时候有一个需要注意的点,我们需要保证整个链一定要有一个节点能够处理当前请求,不然在请求传递到最后一个节点还处理不了时,会报空指针异常,因为最后一个节点的nextHandler没有设置,我们这里的处理是判断如果nextHandler为空,证明当前节点已经是最后一个,直接返回,证明本次请求不需要提交发票申请。也可以定义一个可以匹配所有请求的最终节点,当前面的所有节点都无法处理的时候由这个节点做一个默认处理。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值