设计模式之责任链模式

1. 责任链模式

计算机软件是用来处理信息的,有多种不同的方式来组织和处理信息。当我们讨论面向对象编程时,应该赋予一个类单一的职责,从而使得类容易维护和扩展。设想一个场景,需要对一批从客户端来的数据进行多种不同的操作,我们会使用多个不同的类负责不同的操作,而不是使用一个类集成所有的操作,这样做能够让代码松耦合且简洁。这些类被称为处理器,第一个处理器会接收请求,如果它需要执行操作则会进行一次数据处理,如果不需要则会将请求传递给第二个处理器,依次类推直至走完整个链,这就是责任链模式。

在这里插入图片描述

责任链模式优点:

  • 降低了对象之间的耦合度。
  • 增强了系统的可扩展性,根据需要可以增加处理器,满足开闭原则。
  • 增强了指派职责的灵活性,当工作流发生变化时,可以动态改变链内的处理器的次序,或者动态新增、删除职责。
  • 责任分担,每个类只需要处理自己该处理的工作,不需要处理的请求传递给下一个处理器,符合单一职责原则。

责任链模式缺点:

  • 不能保证每个请求一定被处理,因为一个请求并没有明确的处理者,该请求可能一直到链的末端都得不到处理。
  • 对于较长的责任链,请求处理可能涉及多个处理对象,系统性能将受到一定影响。
  • 一定要避免出现死循环情况。

责任链模式结构如下:

在这里插入图片描述

  • 客户端(Client):客户端是使用责任链模式的应用程序的主要结构,它的职责是实例化一个处理器链,然后在责任链的头部处理器处发起请求。
  • 抽象处理器(Handler):处理器的抽象基类或接口,提供给具体处理器继承或实现。
  • 具体处理器(Handler1、Handler2):实现了处理器接口的具体处理器,内部维持一个引用,指向链中的下一个处理器。

2. 责任链案例

在学校的请假需求中,规定学生请假小于2天,班主任可以予以审批,请假天数超过2天小于7天班主任需要交给系主任进行审批,但请假天数超过7天是需要交由校长进行审批,通过程序实现如下:

新建抽象处理者类,这里使用接口和抽象类,接口名为Handler,定义处理器行为,内容如下:

public interface Handler {

    /**
     * 设置下一个处理者
     * @param handler 处理者
     */
    void setNextHandler(Handler handler);

    /**
     * 获取下一个处理者
     * @return 处理者
     */
    Handler getNextHandler();

    /**
     * 处理请假请求
     * @param holiday 请假天数
     */
    void handleRequset(Integer holiday);
}

由于每个处理器都会设置下一级处理器,在抽象类中实现设置下一级处理器公共方法,类名为AbstractHandler,内容如下:

public abstract class AbstractHandler implements Handler {

    /**
     * 下一个处理者
     */
    protected Handler nextHandler;

    @Override
    public void setNextHandler(Handler handler) {
        this.nextHandler = handler;
    }

    @Override
    public Handler getNextHandler() {
        return this.nextHandler;
    }
}

新建班主任处理者类继承抽象处理者类,实现请求处理方法,类名称为ChargeThacherHandler,内容如下:

public class ChargeThacherHandler extends AbstractHandler {

    @Override
    public void handleRequset(Integer holiday) {
        if (holiday <= 2){
            System.out.println(String.format("班主任:请假%d天,审批通过", holiday));
        } else {
            System.out.println("班主任:请假天数超出我的审批范围,交由下级审批");
            getNextHandler().handleRequset(holiday);
        }
    }

}

新建系主任处理者类继承抽象处理者类,实现请求处理方法,类名称为DeanHandler,内容如下:

public class DeanHandler extends AbstractHandler{

    @Override
    public void handleRequset(Integer holiday) {
        if (holiday <= 7){
            System.out.println(String.format("系主任:请假%d天,审批通过", holiday));
        } else {
            System.out.println("系主任:请假天数超出我的审批范围,交由下级审批");
            getNextHandler().handleRequset(holiday);
        }
    }
}

新建王校长处理者类继承抽象处理者类,实现请求处理方法,类名称为HeadMasterHandler,内容如下:

public class HeadMasterHandler extends AbstractHandler {
    
    @Override
    public void handleRequset(Integer holiday) {
        if (holiday <= 10){
            System.out.println(String.format("王校长:请假%d天,审批通过", holiday));
        } else {
            System.out.println("王校长:请假天数太长,不予以批准。");
        }
    }
}

新建客户端类进行责任链的设置并发起请假请求,类名称为Client,内容如下:

public class Client {
    public static void main(String[] args) {
        // 组装责任链
        Handler chargeThacherHandler = new ChargeThacherHandler();
        Handler deanHandler = new DeanHandler();
        Handler headMasterHandler = new HeadMasterHandler();
        // 班主任的下一级是系主任
        chargeThacherHandler.setNextHandler(deanHandler);
        // 系主任的下一级是王校长
        deanHandler.setNextHandler(headMasterHandler);

        // 提出请假请求

        // 请求休假1天
        chargeThacherHandler.handleRequset(1);
        System.out.println("-------------------------------------------");

        // 请求休假5天
        chargeThacherHandler.handleRequset(5);
        System.out.println("-------------------------------------------");

        // 请求休假8天
        chargeThacherHandler.handleRequset(8);
        System.out.println("-------------------------------------------");

        // 请求休假20天
        chargeThacherHandler.handleRequset(20);
    }
}

在这里插入图片描述

不同的请假请求依次传递给合适的角色审批,各个角色职责单一。

3. 责任链应用

  • 事件处理器:JS的点击事件通过冒泡的方式依次传递。
  • 过滤器链和拦截器链:Java的Servlet规范中的过滤器链和Spring MVC以及Struts中的拦截器链。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值