责任链模式

作者: Jackson杰 | 来源:发表于2019-04-24 15:47 被阅读22次

    一 定义

    责任链模式是行为型设计模式之一。所谓链,是指多个节点首尾相连所构成的模式。对于链式结构,每个节点都可以被拆来再连接,因此链式结构有很好的灵活性。应用到编程领域,将每个节点看做是一个对象,每个对象拥有不同的处理逻辑,将一个请求从链式的首端出发,沿着链式的路径依次传递给每一个节点对象,直至对象处理这个请求为止。

    定义:使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。

    二 模式结构

    角色介绍

    • Handler:抽象处理角色,声明一个请求处理的方法,并在其中保持一个对下一个处理节点Handler对象的引用。
    • ConcreteHandler:具体的处理角色,对请求进行处理,如果不能进行处理,就将请求发送给下一个节点的处理对象。

    三 通用代码

    下面是一个责任链模式简化版的模式代码。

    • 抽象处理者
    /*
     * 抽象处理者
     * @author Jackson
     * @version 1.0.0
     * since 2019 04 23
     */
    public abstract class Handler {
    
        protected Handler successor; // 下一个节点的处理者
    
        /**
         * 请求处理
         * @param condition  请求条件
         */
        public abstract void handleRequest(String condition);
    }
    
    • 具体的处理者1
    public class ConcreteHandler1 extends Handler{
    
        @Override
        public void handleRequest(String condition) {
            if (condition.equals("ConcreteHandler1")){
                System.out.println("ConcreteHandler1 handled");
                return;
            }else {
                successor.handleRequest(condition);
            }
        }
    }
    
    • 具体的处理者2
    public class ConcreteHandler2 extends Handler{
    
        @Override
        public void handleRequest(String condition) {
            if (condition.equals("ConcreteHandler2")){
                System.out.println("ConcreteHandler2 handled");
                return;
            }else {
                successor.handleRequest(condition);
            }
        }
    }
    
    • 测试代码
    
            // 构造一个ConcreteHandler1对象
            ConcreteHandler1 handler1=new ConcreteHandler1();
    
            // 构造一个ConcreteHandler2对象
            ConcreteHandler2 handler2=new ConcreteHandler2();
    
             // 设置handler1的下一个节点
            handler1.successor=handler2;
    
            // 设置handler2的下一个节点
            handler2.successor=handler1;
    
            // 处理请求
            handler1.handleRequest("ConcreteHandler1");
    

    运行结果不贴图了,测试代码是交给ConcreteHandler1处理。

    上面是一个简化版的通用代码模式,因为对于请求来说,形式是固定的,是一个字符串,判断一个节点是否能处理该请求,是看该字符串是否和条件匹配。然而在大多数情况下,责任链的请求和对应的处理规则不尽相同,在这种情况下,可以将请求进行封装,同时对请求的规则进行封装。


    模式代码如下:

    • 抽象请求者
    public abstract class AbstractRequest {
    
        private Object obj;
    
        public AbstractRequest(Object obj) {
            this.obj = obj;
        }
    
        /**
         * 获取处理的内容对象
         * @return
         */
        public Object getContent(){
            return obj;
        }
    
        /**
         * 获取请求级别
         * @return
         */
        public abstract int getRequestLevel();
    }
    
    • 抽象处理者
    public abstract class AbstractHandler {
    
        protected AbstractHandler nexthandler;  // 下一节点上的处理者对象
    
        public final void handleRequest(AbstractRequest request){
            // 判断当前处理者对象的处理级别是否与请求者的级别一致
            if (getHandleLevel()==request.getRequestLevel()){
                // 一致则由该处理对象处理
                handle(request);
            }else {
                // 否则将该请求对象转发给下一个节点上的请求对象
                if (nexthandler!=null){
                    nexthandler.handle(request);
                }else {
                    // 当前所有处理者对象均不能处理该请求时输出
                    System.out.println("All of handler can  not handle the request!");
                }
            }
    
        }
    
    
        /**
         * 获取处理者对象的处理级别
         * @return
         */
        protected abstract int getHandleLevel();
    
    
        /**
         * 每个处理者对象的具体处理方式
         * @param request
         */
        protected abstract void handle(AbstractRequest request);
        
    }
    
    • 具体请求者
    public class Request1 extends AbstractRequest{
    
        public Request1(Object obj) {
            super(obj);
        }
    
        @Override
        public int getRequestLevel() {
            return 1;
        }
    }
    
    public class Request2 extends AbstractRequest{
    
        public Request2(Object obj) {
            super(obj);
        }
    
        @Override
        public int getRequestLevel() {
            return 2;
        }
    }
    
    public class Request3 extends AbstractRequest{
    
        public Request3(Object obj) {
            super(obj);
        }
    
        @Override
        public int getRequestLevel() {
            return 3;
        }
    }
    
    
    • 具体处理者
    public class Handler1 extends AbstractHandler{
    
        @Override
        protected int getHandleLevel() {
            return 1;
        }
    
        @Override
        protected void handle(AbstractRequest request) {
            System.out.println("Handler1 handle request:"+request.getRequestLevel());
        }
    }
    
    public class Handler2 extends AbstractHandler{
    
        @Override
        protected int getHandleLevel() {
            return 2;
        }
    
        @Override
        protected void handle(AbstractRequest request) {
            System.out.println("Handler2 handle request:"+request.getRequestLevel());
        }
    }
    
    public class Handler3 extends AbstractHandler{
    
        @Override
        protected int getHandleLevel() {
            return 3;
        }
    
        @Override
        protected void handle(AbstractRequest request) {
            System.out.println("Handler3 handle request:"+request.getRequestLevel());
        }
    }
    
    • 测试代码
     // 构造三个处理对象
            AbstractHandler handler11=new Handler1();
            AbstractHandler handler12=new Handler2();
            AbstractHandler handler13=new Handler3();
            // 设置当前处理对象的下一个节点的处理者对象
            handler11.nexthandler=handler12;
            handler12.nexthandler=handler13;
            // 构造三个请求对象
            AbstractRequest request1=new Request1("Request1");
            AbstractRequest request2=new Request2("Request2");
            AbstractRequest request3=new Request3("Request3");
    
            // 从链式的首端发起请求
            handler11.handleRequest(request1);
            handler11.handleRequest(request2);
            handler11.handleRequest(request3);
    
    • 运行结果


    我们从链式的首端开始处理请求,当请求时request1时,handler11就可以处理,当请求时request2时,handler11就不能处理了,知道handler12才能处理,以此类推。

    四 实例

    下面举一个具体的实例,以公司走合同为例,小民要签一个合同,总价10w,小民向组领导提交申请,组领导一看,我的权限只能批准2w内的合同,就往上提交给了部门负责人,部门负责人一看,总额不小啊,我只能批准5w以内的合同,然后提交给了公司领导,公司领导就有权限批准了。就这样层层往上传达,直到遇到有权限处理的人。具体代码如下:

    • 抽象领导类
      在这个抽象类中主要做了两件事,一是定义了两个抽象方法来确定领导应有的行为和属性,而是声明了一个处理合同请求的方法来确定当前领导是否有能力处理合同。如果没有处理权限,就将请求转发给上级领导处理,知道遇到有能力处理的领导。
    public abstract class Leader {
    
        protected Leader nextHandler;  // 上级领导处理者
    
        /**
         * 处理合同
         * @param money
         */
        public void handleRequest(int money){
            if (money<=getLimit()){
                handle(money);
            }else {
                if (nextHandler!=null){
                    nextHandler.handleRequest(money);
                }
            }
        }
    
    
        /**
         * 自身能批复的额度权限
         * @return
         */
        protected abstract int getLimit();
    
        /**
         * 处理合同行为
         * @param money
         */
        protected abstract void handle(int money);
    }
    
    • 具体的领导
    public class GroupLeader extends Leader{
    
        @Override
        protected int getLimit() {
            return 20000;
        }
    
        @Override
        protected void handle(int money) {
            System.out.println("组领导审批合同金额:"+money);
        }
    }
    
    public class DepartmnetLeader extends Leader{
        @Override
        protected int getLimit() {
            return 50000;
        }
    
        @Override
        protected void handle(int money) {
            System.out.println("部门领导审批合同金额:"+money);
        }
    }
    
    
    public class CompanyLeader extends Leader{
        @Override
        protected int getLimit() {
            return 100000;
        }
    
        @Override
        protected void handle(int money) {
            System.out.println("公司领导审批合同金额:"+money);
        }
    }
    
    • 测试代码
    // 构建各个领导
            Leader groupLeader=new GroupLeader();
            Leader departmentLeader=new DepartmnetLeader();
            Leader companyLeader=new CompanyLeader();
            // 设置上一级领导处理者
            groupLeader.nextHandler=departmentLeader;
            departmentLeader.nextHandler=companyLeader;
    
            // 发起合同申请
            groupLeader.handleRequest(10000);
            groupLeader.handleRequest(30000);
            groupLeader.handleRequest(80000);
    
    • 运行结果



      可以看到,不同领导处理的权限是不同的。

    五 优缺点

    优点:请求者和处理者解耦合,请求者可以不用知道是谁处理的,处理者也可以不知道请求者,提高了代码的灵活性。
    缺点:性能问题,每个请求都从链的开端遍历到链尾,如果链比较长时,性能将会是一个很大的问题。

    六 使用场景

    • 多个对象可以处理同一请求,但具体哪个对象处理则在运行时决定。
    • 在请求处理者不明确的情况下想多个对象提交请求。
    • 需要动态指定一组对象处理请求。

    相关文章

      网友评论

        本文标题:责任链模式

        本文链接:https://www.haomeiwen.com/subject/npfygqtx.html