• 第十六章·职责链模式


    一、职责链模式概述

    定义:

    职责链模式:避免讲一个请求的发送者和接收者耦合在一起,让多个对象都有机会处理请求。将接收请求的对象连接成一条链,并且沿着这条链传递请求,直到有一个对象能够处理它为止。

    二、职责链模式结构和实现

    2.1 职责链模式结构

    职责链模式包含2个角色:

    1. Handler(抽象处理者):定义了一个处理请求的接口,定义了一个抽象处理者类型的对象,作为其下家的引用,通过该引用处理者可以连成一条链;
    2. ConcreteHandler(具体处理者):它是抽象处理者的子类,可以处理用户的请求,在处理请求之前需要进行判断,看是否有相应的处理权限,如果可以处理请求就处理它,否则将请求转发给后继者进行处理。

    2.2 职责链模式实现

    //请假单,充当请求类

    /**
     * 请假单
     */
    public class WrittenRequest {
    
        //请假人
        private String username;
    
        //请假内容
        private String content;
    
        //请假天数
        private int day;
    
        public WrittenRequest(String username, String content, int day) {
            this.username = username;
            this.content = content;
            this.day = day;
        }
    
        public String getUsername() {
            return username;
        }
        public void setUsername(String username) {
            this.username = username;
        }
        public String getContent() {
            return content;
        }
        public void setContent(String content) {
            this.content = content;
        }
        public int getDay() {
            return day;
        }
        public void setDay(int day) {
            this.day = day;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    //审批者,充当抽象处理者

    /**
     * 抽象审批者
     */
    public abstract class Approver {
    
        protected Approver successor;//定义后继者对象
        protected String name;//审批者姓名
    
        public Approver(String name){
            this.name = name;
        }
    
        public void setSuccessor(Approver successor) {
            this.successor = successor;
        }
    
        public abstract void handler(WrittenRequest request);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    //具体处理者

    /**
     * 主任
     */
    public class Director extends Approver {
    
    
        public Director(String name) {
            super(name);
        }
    
        @Override
        public void handler(WrittenRequest request) {
            if (request.getDay() < 3) {
                System.out.println("[主任]" + name + "审批并通过了");
            } else {
                this.successor.handler(request);
            }
        }
    }
    
    /**
     * 经理
     */
    public class Manager extends Approver {
    
    
        public Manager(String name) {
            super(name);
        }
    
        @Override
        public void handler(WrittenRequest request) {
            if (request.getDay() >= 3 && request.getDay() < 10) {
                System.out.println("[经理]" + name + "审批并通过了");
            } else {
                this.successor.handler(request);
            }
        }
    }
    
    /**
     * 总经理
     */
    public class GeneralManager extends Approver{
    
        public GeneralManager(String name) {
            super(name);
        }
    
        @Override
        public void handler(WrittenRequest request) {
            if (request.getDay() >= 10 && request.getDay() <= 30) {
                System.out.println("[总经理]" + name + "审批并通过了");
            } else {
                System.out.println("请假超过30天,拒绝此申请!");
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    //客户端

    public class Client {
    
        public static void main(String[] args) {
    
            /**
             * 案例需求描述:
             * 某OA系统需要提供一个假条审批模块;
             * 如果员工请假天数小于3天,主任可以审批该请假条;
             * 如果员工请假天数大于等于3天,小于10天,经理可以审批;
             * 如果员工请假天数大于等于10天,小于等于30天,总经理可以审批;
             * 如果员工请假天数大于30天,则总经理也不可以审批,提示拒绝信息;
             * 请使用职责链模式设计该功能模块。
             */
    
            WrittenRequest request1 = new WrittenRequest("张三","生病请假",2);
            WrittenRequest request2 = new WrittenRequest("李四","旅游请假",5);
            WrittenRequest request3 = new WrittenRequest("王五","陪产假",23);
            WrittenRequest request4 = new WrittenRequest("赵六","休息请假",31);
    
            Approver zhangfei,guanyu,liubei;
            zhangfei = new Director("张飞");
            guanyu = new Manager("关羽");
            liubei = new GeneralManager("刘备");
    
            zhangfei.setSuccessor(guanyu);
            guanyu.setSuccessor(liubei);
    
            zhangfei.handler(request1);
            zhangfei.handler(request2);
            zhangfei.handler(request3);
            zhangfei.handler(request4);
    
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    三、职责链模式的优缺点和适用环境

    3.1 职责链模式的优点

    1. 使一个对象无需知道是其他哪一个请求对象处理其请求,降低了系统的耦合度;
    2. 简化了对象之间的相互连接;
    3. 给对象职责的分派带来更多的灵活性;
    4. 增加一个新的具体请求处理者较为方便。

    3.2 职责链模式的缺点

    1. 不能保证请求一定会被处理;
    2. 对于比较长的职责链,系统性能将受到一定的影响;
    3. 如果建链不当,可能会造成循环调用,将导致系统陷入死循环。

    3.3 职责链模式的适用环境

    1. 有多个对象可以处理同一个请求,具体哪个对象处理该请求待运行时刻再确定;
    2. 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求;
    3. 可动态指定一组对象处理请求,客户端可以动态创建职责链来处理请求,还可以改变链中处理者之间的先后次序。

    【参考文献】:
    本文是根据刘伟的《Java设计模式》一书的学习笔记,仅供学习用途,勿做其他用途,请尊重知识产权。

    【本文代码仓库】:https://gitee.com/xiongbomy/java-design-pattern.git

  • 相关阅读:
    超强 | 保险单据在线OCR,秒速识别保单信息
    Ansible 企业实战详解
    go-kit-consul client服务发现源码分析
    一种基于暗通道先验算法的图像去雾技术研究
    vscode开发STM32(三)---调试篇
    【SpringBoot篇】分页查询 | 扩展SpringMvc的消息转换器
    模板编程:采用vector作为底层实现stack的功能(包括初始化列表和迭代器的实现)
    java计算机毕业设计河东街摊位管理系统源码+mysql数据库+系统+LW文档+部署
    一个依赖搞定Spring Boot 配置文件脱敏
    【C++】设计模式
  • 原文地址:https://blog.csdn.net/weixin_44143114/article/details/126514436