设计模式--责任链模式(Chain of Responsibility)

一 引入

在实际开发中的应用 扩展springboot内置异常拦截器–自定义全局异常处理组件 可参考笔者文章

Chain of Responsibility模式名为责任链模式,是一种行为型模型,使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

首先看看什么叫推卸责任,我们去公司申请财务报销,当找到财务时填写报销单后,被告知金额太大只能找财务主管批,于是我们拿着资料去找财务主管,财务主管说金额还是太大只能找老板批。这里相当于将责任传递下去即推卸责任。原因是每个财务能审批的最大金额是不一样的

通过上面的报销例子,我们可以看到自己因为报销找了很多人,这些人相当于一个链条,即第一个不能解决那么找第二个(财务主管),第二个不能解决找第三个(老板)直到找到到底该谁来进行审批即谁来处理。

二 uml 类图

在这里插入图片描述

  • Handler : 抽象的处理者, 定义了一个处理请求的接口, 同时含义另外Handler
  • ConcreteHandlerA , B 是具体的处理者, 处理它自己负责的请求, 可以访问它的后继者(即下一个处理者), 如果可以处理当前请求,则处理,否则就将该请求交个 后继者去处理,从而形成一个职责链
  • Request 含义很多属性,表示一个请求

二 代码实现

定义接口及公用抽象

public interface Financial {
    /**
     * 报账处理
     * @param reimbursement
     */
    void process(Reimbursement reimbursement);

    /**
     * 下一个处理节点
     * @param financial
     * @return
     */
    Financial nextFinancial(Financial financial);
}
public abstract class AbstractFinancial implements Financial {

    private  Financial financial;
    @Override
    public void process(Reimbursement reimbursement) {
       // 通过模板方法定义子类的处理
        if (!doProcess(reimbursement)&&this.financial!=null){
            // 下节点处理
            financial.process(reimbursement);
        }
    }

    @Override
    public Financial nextFinancial(Financial financial) {
        this.financial=financial;
        return financial;
    }

    abstract Boolean doProcess(Reimbursement reimbursement);


    public void outMessage(String name,String reimbursementName){
        String format = String.format("%s有权限处理%s的报账", name, reimbursementName);
        System.out.println(format);
    }
}

定义具体实现

public class Finance extends AbstractFinancial{
    @Override
    Boolean doProcess(Reimbursement reimbursement) {
        if (reimbursement.getAmount()<2000D){
            outMessage("财务",reimbursement.getName());
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }
}
public class Manager extends AbstractFinancial{
    @Override
    Boolean doProcess(Reimbursement reimbursement) {
        if (reimbursement.getAmount()<5000D){
            outMessage("财务总监",reimbursement.getName());
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }
}

public class CFO extends AbstractFinancial{
    @Override
    Boolean doProcess(Reimbursement reimbursement) {
        outMessage("boos",reimbursement.getName());
        return Boolean.TRUE;
    }
}

提供对外管理器

public class FinancialManger {
    public static Financial financial;
    static {
        Finance finance = new Finance();
        Manager manager = new Manager();
        CFO cfo = new CFO();

        // 设置关系
        finance.nextFinancial(manager);
        manager.nextFinancial(cfo);

        financial=finance;
    }
}

三 客户端调用

public class Client {
    public static void main(String[] args) {
        Reimbursement reimbursement = new Reimbursement();
        reimbursement.setAmount(500D);
        reimbursement.setName("test1");
        FinancialManger.financial.process(reimbursement);
    }
}

四 在源码中的应用

在这里插入图片描述

在这里插入图片描述

五 总结

  • 将请求和处理分开,实现解耦,提高系统的灵活性

  • 简化了对象,使对象不需要知道链的结构

  • 性能会受到影响,特别是在链比较长的时候,因此需控制链中最大节点数量,一般通过在 Handler 中设置一个最大节点数量,在 setNext()方法中判断是否已经超过阀值,超过则不允许该链建立,避免出现超长链无意识地破坏系统性能

  • 调试不方便。采用了类似递归的方式,调试时逻辑可能比较复杂

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值