Java设计模式学习记录-责任链模式

前言

 已经把五个创建型设计模式和七个结构型设计模式介绍完了,从这篇开始要介绍行为型设计模式了,第一个要介绍的行为型设计模式就是责任链模式(又称职责链模式)。

责任链模式

概念介绍

责任链模式是为了避免请求的发送者和接收者之间的耦合关系,使多个接收对象都有机会处理请求。将这些对象练成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。当然责任链中也有可能没有可以处理该请求的对象,这种情况是允许发生的。

举例

还是以前的规律,先举出具体的代码例子,然后再分析。拿前阵子在我老东家发生的一件事情来说,同事小王要结婚了,所以要请假回家筹备婚礼,但是公司有明确的规章制度,请假需要提前申请,并且每一级的领导能够审批的假期天数也不一样,部门经理可以审批12天的假期,技术总监能够审批3到5天的假期,大于5天的就要找CEO审批了,如果CEO审批通过了才可以休息5天以上的假期,小王筹备婚礼和渡蜜月总共要请10个工作日的假期。

用代码来实现这个过程就是下面?这个样子的。

先创建请假条类

/**
 * 请假条
 */
@Data
@AllArgsConstructor
public class Leave {

    /* 部门 */
    private String department;
    /* 员工名称 */
    private String name;
    /* 请假天数 */
    private double days;
    /* 请假事由 */
    private String cause;

}

然后创建审批人的抽象类

/**
 * 审批人
 */
public abstract class Approver {

    /* 审批人名称 */
    String name;
    /* 下一个审批人 */
    Approver nextApprover;

    public Approver(String name){
        this.name = name;
    }

    /**
     * 设置下一个审批人
     * @param approver
     */
    public void setNextApprover(Approver approver){
        this.nextApprover = approver;
    }

    /**
     * 审批
     * @param leave
     */
    public abstract void approval(Leave leave);

}

部门经理

/**
 * 部门经理
 */
public class Manager extends Approver {

    /**
     * 设置名称
     * @param name 领导名称
     */
    public Manager(String name) {
        super(name);
    }

    /**
     * 审批
     * @param leave 请假条
     */
    @Override
    public void approval(Leave leave) {

        if(leave.getDays()<3){
            System.out.println("请假小于3天,算临时休息,批准了。");
            System.out.println("部门经理审批通过---------审批流程over。");
        }else{
            if(Objects.nonNull(nextApprover)){
                System.out.println("部门经理批准不了这么多天的假期,需要上级审批。");
                this.nextApprover.approval(leave);
            }else{
                System.out.println(name+"的领导不在,等着吧。");
            }
        }

    }


}

技术总监

/**
 * 技术总监
 */
public class TechnicalDirector extends Approver {

    /**
     * 设置名称
     * @param name 领导名称
     */
    public TechnicalDirector(String name) {
        super(name);
    }

    /**
     * 审批
     * @param leave 请假条
     */
    @Override
    public void approval(Leave leave) {
        if(leave.getDays()<5){
            System.out.println("请假小于5天,算有事休息,批准了。");
            System.out.println("技术总监审批通过---------审批流程over。");
        }else{
            if(Objects.nonNull(nextApprover)){
                System.out.println("技术总监批准不了这么多天的假期,需要上级审批。");
                this.nextApprover.approval(leave);
            }else{
                System.out.println(name+"的领导不在,等着吧。");
            }
        }
    }
}

CEO

/**
 * CEO
 */
public class CEO extends Approver {

    /**
     * 设置名称
     * @param name 领导名称
     */
    public CEO(String name) {
        super(name);
    }

    /**
     * 审批
     * @param leave 请假条
     */
    @Override
    public void approval(Leave leave) {

        if(leave.getDays()>5&&leave.getDays()<=10){
            System.out.println("情况特殊,批准了。");
            System.out.println("CEO审批通过---------审批流程over。");
        }else{
            System.out.println(name+"说请假的时间太长了不批,最好别一次性请这么久。");
        }

    }
}

测试类

public class Client {

    public static void main(String[] args) {

        //写请假条
        Leave leave = new Leave("技术部","小王",6.0,"结婚");



        //创建审批节点
        Approver zhangge = new Manager("张哥");
        Approver laozhao = new TechnicalDirector("老赵");
        Approver lizong = new CEO("李总");

        //将审批节点串起来
        zhangge.setNextApprover(laozhao);
        laozhao.setNextApprover(lizong);

        //开始审批
        zhangge.approval(leave);
    }

}

运行结果

部门经理批准不了这么多天的假期,需要上级审批。
技术总监批准不了这么多天的假期,需要上级审批。
情况特殊,批准了。
CEO审批通过---------审批流程over。

通过运行结果,我们可以看出来,当请假天数为10天时,部门经理和技术总监都已经处理不了了,然后抛给了CEO,通过CEO特批小王的婚假请求才算了审批完成。这个例子就是用到了我们今天说的责任链模式,下面继续分析责任链模式。

责任链模式分析

责任链的结构图

主要涉及到的角色

抽象处理者(Handler)角色:抽象处理者用于定义出一个处理请求的接口,如果需要,接口可以定义出一个方法,以返回对下一个处理对象的引用。上面例子中的Approver就是代表的这个角色。

具体处理者(ConcreteHandler)角色:处理接到的请求,可以选择将请求处理掉,或者将请求传递给下家。上面的例子中的Manager和TechnicalDirector以及CEO就是代表的这个角色。

责任链模式总结

纯的责任链模式和不纯的责任链模式

  • 纯的责任链模式要求一个具体的处理者对象只能在两个行为中选择一个:一个是承担责任;二是把责任推给下家。不允许出现某一个具体处理者对象在承担了一部分责任后又把责任向下传的情况。在一个纯的责任链中,一个请求必须被某一个处理者对象所接受。
  • 不纯的责任链模式中允许某个请求被一个具体处理者部分处理后再向下传递,或者一个具体处理者处理完某请求后其后继处理者可以继续处理该请求,而且一个请求可以最终不被任何处理者对象所接收。例如JavaScript中的事件冒泡。

责任链模式的优点

1、请求不需要指出被哪个对象处理了,这样的效果是请求者和接收者之间的解耦,而且链中的对象也不需要清楚其他链的结构,也降低了耦合。

2、请求处理对象仅需要维护一个指向其后继者的的引用,而不需要维护所有的处理对象,简化了对象之间的相互连接。

3、在给对象分派职责时,职责链可以给我们更多的灵活性,可以通过在运行时对该链进行动态的增加或修改来增加或改变处理一个请求的职责。

4、新增一个请求处理对象,不需要改动现有代码,只需要重新设置连接即可,符合“开闭原则”。

责任链模式的缺点

1、如果一个请求没有明确的接收者,那么就不能保证它一定会被处理,该请求可能一直到链的末端都得不到处理;一个请求也可能因职责链没有被正确配置而得不到处理。

2、 对于比较长的职责链,请求的处理可能涉及到多个处理对象,不仅增加了代码的复杂性并且系统性能也将受到一定影响,而且在进行代码调试时不太方便。

3、若建链不当,可能会造成循环调用,将导致系统陷入死循环。

适用场景

1、有多个对象可以处理同一个请求,具体哪个对象处理该请求待运行时刻再确定,客户端只需将请求提交到链上,而无须关心请求的处理对象是谁以及它是如何处理的。

2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。

3、可动态指定一组对象处理请求,客户端可以动态创建职责链来处理请求,还可以改变链中处理者之间的先后次序。

其实在我们日常开发中也会有适用到责任链模式的场景,try/catch、servlet(各个servelt互相调用)、以及filter等

想了解更多的设计模式请查看Java设计模式学习记录-GoF设计模式概述

现在是不是行业不景气呢?怎么最近连面试机会都少了?

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏余林丰

命令模式

当学了这个命令模式后,又一次体会到编程的艺术,明明一个看似很简单的事,却要用“复杂”的方法来实现,就像在之前我多次说到的,其实并不是“复杂”,并不是“难”,而是...

1729
来自专栏狮乐园

【译】Understanding SOLID Principles - Dependency Inversion

当我们在读书,或者在和一些别的开发者聊天的时候,可能会谈及或者听到术语SOILD。在这些讨论中,一些人会提及它的重要性,以及一个理想中的系统,应当包含它所包含的...

943
来自专栏斑斓

我们的技术实践

本文是我在中生代技术群分享的话题《创业一年经历的技术风雨》中的第三部分《研发团队总结的技术实践》。若要阅读第二部分《技术团队的管理》,请移步中生代技术群公众号。...

3305
来自专栏积累沉淀

Java设计模式(十七)----责任链模式

责任链模式 一、 概念 二、 引子 三、 结构 四、 具体案例 一、概念 责任链模式是一种对象的行为模式。...

1899
来自专栏java一日一条

有经验的Java开发者和架构师容易犯的10个错误(上)

首先允许我们问一个严肃的问题?为什么Java初学者能够方便的从网上找到相对应的开发建议呢?每当我去网上搜索想要的建议的时候,我总是能发现一 大堆是关于基本入门的...

782
来自专栏Java学习网

最佳编码实践:搞砸代码的10种方法

 这是一篇提供有效、实用编程方法的程序箴言,作者Susan Harkins是世界最大的技术期刊出版社的主编,具有多年的实践经验;在这篇文章里她重申“最佳编码实践...

2714
来自专栏java一日一条

Jsoup代码解读之四-parser(上)

作为Java世界最好的HTML 解析库,Jsoup的parser实现非常具有代表性。这部分也是Jsoup最复杂的部分,需要一些数据结构、状态机乃至编译器的知识。...

961
来自专栏分布式系统和大数据处理

RPG设计(物品锻造与Decorator模式)

物品锻造是各类奇幻游戏中的常见功能,就拿众所周知的Diablo来说吧。假设角色拥有一把单手剑,可能基础攻击力只有13,但是它有三个装备孔。当给剑镶嵌一颗蓝宝石的...

1513
来自专栏编程

使用JavaScript开发一个自修改代码

话说在25年前,我刚刚开始从事软件开发。在工作中,我遇到一个叫Dave的朋友,他曾在一家大型保险公司工作过几年,他的工作重点是开发支持一个名为“个人人寿保险”的...

2857
来自专栏逍遥剑客的游戏开发

Nebula3中的委托(Delegate)

1183

扫码关注云+社区

领取腾讯云代金券