责任链模式

简介

责任链模式(Chain of Responsibility Pattern)将链中每一个节点都看作一个对象,每个节点处理的请求均不同,且内部自动维护下一个节点对象。当一个请求从链式的首端发出时,会沿着责任链预设的路径依次传递到每一个节点对象,直至被链中的某个对象处理为止,属于行为型设计模式。

通用模板

  1. 创建抽象处理者:定义一个请求处理的方法,并维护一个下一处理节点Handler对象的引用。

    java 复制代码
    // 抽象处理者
    public abstract class Handler {
        protected Handler nextHandler;
    
        public void setNextHandler(Handler nextHandler) {
            this.nextHandler = nextHandler;
        }
    
        public abstract void handleRequest(String request);
    }
  2. 创建具体处理者:对请求进行处理,如果不感兴趣,则进行转发。

    java 复制代码
    // 具体处理者A
    public class ConcreteHandlerA extends Handler {
        @Override
        public void handleRequest(String request) {
            if ("requestA".equals(request)) {
                System.out.println(this.getClass().getSimpleName() + " deal with request:" + request);
                return;
            }
    
            if (this.nextHandler != null){
                this.nextHandler.handleRequest(request);
            }
        }
    }
    java 复制代码
    // 具体处理者B
    public class ConcreteHandlerB extends Handler {
        @Override
        public void handleRequest(String request) {
            if ("requestB".equals(request)) {
                System.out.println(this.getClass().getSimpleName() + " deal with request:" + request);
                return;
            }
    
            if (this.nextHandler != null){
                this.nextHandler.handleRequest(request);
            }
        }
    }

说明: 在上面代码中,我们把消息硬编码为String类型,而在真实业务中,消息是具备多样性的,可以是int、String或者自定义类型。因此,在上面代码的基础上,可以对消息类型进行抽象Request,增强了消息的兼容性。

模板测试

  1. 测试代码

    java 复制代码
    public class Client {
        public static void main(String[] args) {
            Handler handlerA = new ConcreteHandlerA();
            Handler handlerB = new ConcreteHandlerB();
            // 设置责任链
            handlerA.setNextHandler(handlerB);
            // 创建请求:我们把消息硬编码为String类型,而在真实业务中,
            // 消息是具备多样性的,可以是int、String或者自定义类型。
            // 因此,在上面代码的基础上,可以对消息类型进行抽象Request,增强了消息的兼容性。
            String request = "requestB";
            // 发送请求
            handlerA.handleRequest(request);
        }
    }
  2. 测试结果

    java 复制代码
    ConcreteHandlerB deal with request:requestB

应用场景

在日常生活中,责任链模式是比较常见的。我们平时处理工作中的一些事务,往往是各部门协同合作来完成某一个任务的。而每个部门都有各自的职责,因此,很多时候事情完成一半,便会转交到下一个部门,直到所有部门都审批通过,事情才能完成。还有我们平时说的"过五关,斩六将"其实就是闯关,也是责任链模式的一种应用场景。

责任链模式主要解耦了请求与处理,客户只需将请求发送到链上即可,不需要关心请求的具体内容和处理细节,请求会自动进行传递,直至有节点对象进行处理。责任链模式主要适用于以下应用场景。 (1)多个对象可以处理同一请求,但具体由哪个对象处理则在运行时动态决定。

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

(3)可动态指定一组对象处理请求。

优点

(1)将请求与处理解耦。

(2)请求处理者(节点对象)只需关注自己感兴趣的请求进行处理即可,对于不感兴趣的请求,直接转发给下一个节点对象。

(3)具备链式传递处理请求功能,请求发送者不需要知晓链路结构,只需等待请求处理结果即可。 (4)链路结构灵活,可以通过改变链路结构动态地新增或删减责任。

(5)易于扩展新的请求处理类(节点),符合开闭原则。

缺点

(1)责任链太长或者处理时间过长,会影响整体性能。

(2)如果节点对象存在循环引用,则会造成死循环,导致系统崩溃。

"生搬硬套"实战

场景描述

我们将使用责任链模式来处理员工请假申请的例子。在这个例子中,我们有三种类型的请假请求:病假、事假和年假。每个请求将根据请假天数和类型被不同的经理审批。

代码开发
  1. 实战中我们用自定义类来代替模板中的字符串,先自定义一个请假请求类:

    java 复制代码
    // 请假请求类
    public class LeaveRequest {
        private String type;
        private int days;
    
        public LeaveRequest(String type, int days) {
            this.type = type;
            this.days = days;
        }
    
        public String getType() {
            return type;
        }
    
        public int getDays() {
            return days;
        }
    }
  2. 创建抽象处理者(这里指请假请求的handler)

    java 复制代码
    // 请假请求处理者
    public abstract class LeaveRequestHandler {
        protected LeaveRequestHandler nextHandler;
    
        public LeaveRequestHandler setNext(LeaveRequestHandler handler) {
            this.nextHandler = handler;
            return handler;
        }
    
        public abstract void handleRequest(LeaveRequest request);
    }
  3. 创建具体处理者(这里指病假处理者、事假处理者以及年假处理者)

    java 复制代码
    // 病假处理者
    public class SickLeaveHandler extends LeaveRequestHandler {
        @Override
        public void handleRequest(LeaveRequest request) {
            if ("Sick".equals(request.getType())) {
                System.out.println("Sick leave request is handled by " + getClass().getSimpleName());
            } else {
                if (nextHandler != null) {
                    nextHandler.handleRequest(request);
                }
            }
        }
    }
    java 复制代码
    // 事假处理者
    public class PersonalLeaveHandler extends LeaveRequestHandler {
        @Override
        public void handleRequest(LeaveRequest request) {
            if ("Personal".equals(request.getType()) && request.getDays() <= 5) {
                System.out.println("Personal leave request is handled by " + getClass().getSimpleName());
            } else {
                if (nextHandler != null) {
                    nextHandler.handleRequest(request);
                }
            }
        }
    }
    java 复制代码
    // 年假处理者
    public class AnnualLeaveHandler extends LeaveRequestHandler {
        @Override
        public void handleRequest(LeaveRequest request) {
            if ("Annual".equals(request.getType())) {
                System.out.println("Annual leave request is handled by " + getClass().getSimpleName());
            } else {
                if (nextHandler != null) {
                    nextHandler.handleRequest(request);
                }
            }
        }
    }

至此,我们就通过"生搬硬套"责任链模式的模板设计出一套请假申请的案例,接下来我们进行测试:

  • 测试代码

    java 复制代码
    public class Client {
        public static void main(String[] args) {
            LeaveRequestHandler sickHandler = new SickLeaveHandler();
            LeaveRequestHandler personalHandler = new PersonalLeaveHandler();
            LeaveRequestHandler annualHandler = new AnnualLeaveHandler();
    
            // 设置责任链
            sickHandler.setNext(personalHandler).setNext(annualHandler);
    
            // 创建请假请求
            LeaveRequest sickLeave = new LeaveRequest("Sick", 3);
            LeaveRequest personalLeave = new LeaveRequest("Personal", 4);
            LeaveRequest annualLeave = new LeaveRequest("Annual", 7);
    
            // 发送请求
            sickHandler.handleRequest(sickLeave);
            sickHandler.handleRequest(personalLeave);
            sickHandler.handleRequest(annualLeave);
        }
    }
  • 测试结果

    java 复制代码
    Sick leave request is handled by SickLeaveHandler
    Personal leave request is handled by PersonalLeaveHandler
    Annual leave request is handled by AnnualLeaveHandler

总结

责任链模式(Chain of Responsibility)是一种处理请求的模式,它让多个处理器都有机会处理该请求,直到其中某个处理成功为止。责任链模式把多个处理器串成链,然后让请求在链上传递:

相关推荐
liufeismart20249 天前
Android 第三方框架:RxJava:源码分析:责任链模式
责任链模式·rxjava
岳轩子11 天前
23种设计模式之责任链模式
java·设计模式·责任链模式
Damon_041112 天前
责任链模式在Spring中的应用
java·spring·责任链模式
森伯41616 天前
行为型设计模式之《责任链模式》实践
java·设计模式·责任链模式
huaqianzkh17 天前
责任链模式的理解和实践
java·开发语言·责任链模式
姆路19 天前
责任链模式
责任链模式
问道飞鱼22 天前
【知识科普】设计模式之-责任链模式
java·设计模式·责任链模式
请你打开电视看看23 天前
行为型模式-责任链模式
责任链模式
Jack_abu23 天前
设计模式学习之——责任链模式
学习·设计模式·责任链模式
Gordon家的哈士奇23 天前
设计模式之责任链模式
java·设计模式·责任链模式