责任型模式是什么?

不影响客户端的情况下动态地重新组织链和分配任务。


java 责任链模式 执行顺序 责任链模式实例_List

责任链模式示意图

责任链模式的要素

  • 请求发起者
  • 抽象请求发起者
  • 抽象请求处理者
  • 具体的请求处理者

实际例子(此后的例子为转载别人的博客)

1、实例场景

    在公司内部员工请假一般情况是这样的:员工在OA系统中提交一封请假邮件,该邮件会自动转发到你的直接上级领导邮箱里,如果你的请假的情况特殊的话,该邮件也会转发到你上级的上级的邮箱,根据请假的情况天数多少,系统会自动转发相应的责任人的邮箱。我们就以这样一种场景为例完成一个责任链模式的代码。为了更清晰的描述这种场景我们规定如下:

    ① GroupLeader(组长 ):他能批准的假期为2天,如果请假天数超过2天就将请假邮件自动转发到组长和经理邮箱。

    ② Manager(经理):他能批准的假期为4天以内,如果请假天数大于4天将该邮件转发到自动转发到组长、经理和部门领导的邮箱。

    ③ DepartmentHeader(部门领导):他能批准的假期为7天以内,如果大于7天就只批准7天。

 

    我们清楚了上面的场景以后就开始定义模型:

建造者模式(这个模式我现在还不理解)构造Request对象,“请假”对象Request如下:

package myDesignPatternsTest.responsibleModel;

public class Request {
    private String name;

    private String reason;

    private int days;

    private String groupLeaderInfo;

    private String managerInfo;

    private String departmentHeaderInfo;

    private String customInfo;

    public Request(Builder builder) {
        super();
        this.name = builder.name;
        this.reason = builder.reason;
        this.days = builder.days;
        this.groupLeaderInfo = builder.groupLeaderInfo;
        this.managerInfo = builder.managerInfo;
        this.departmentHeaderInfo = builder.departmentHeaderInfo;
        this.customInfo = builder.customInfo;
    }

    public static class Builder {
        public String name;

        public String reason;

        public int days;

        public String groupLeaderInfo;

        public String managerInfo;

        public String departmentHeaderInfo;

        public String customInfo;

        public Builder() {

        }

        public Builder setName(String name) {
            this.name = name;
            return this;
        }

        public Builder setReason(String reason) {
            this.reason = reason;
            return this;
        }

        public Builder setDays(int days) {
            this.days = days;
            return this;
        }

        public Builder setGroupLeaderInfo(String groupLeaderInfo) {
            this.groupLeaderInfo = groupLeaderInfo;
            return this;
        }

        public Builder setManagerInfo(String managerInfo) {
            this.managerInfo = managerInfo;
            return this;
        }

        public Builder setDepartmentHeaderInfo(String departmentHeaderInfo) {
            this.departmentHeaderInfo = departmentHeaderInfo;
            return this;
        }

        public Builder setCustomInfo(String customInfo) {
            this.customInfo = customInfo;
            return this;
        }

        public Builder newRequest(Request request) {
            this.name = request.name;
            this.days = request.days;
            this.reason = request.reason;
            if (request.groupLeaderInfo != null
                    && !request.groupLeaderInfo.equals("")) {
                this.groupLeaderInfo = request.groupLeaderInfo;
            }

            if (request.managerInfo != null && !request.managerInfo.equals("")) {
                this.managerInfo = request.managerInfo;
            }

            if (request.departmentHeaderInfo != null
                    && !request.departmentHeaderInfo.equals("")) {
                this.departmentHeaderInfo = request.departmentHeaderInfo;
            }

            if (request.customInfo != null && !request.customInfo.equals("")) {
                this.customInfo = request.customInfo;
            }


            return this;
        }

        public Request build() {
            return new Request(this);
        }
    }

    public String name() {
        return name;
    }

    public String reason() {
        return reason;
    }

    public int days() {
        return days;
    }

    public String groupLeaderInfo() {
        return groupLeaderInfo;
    }

    public String managerInfo() {
        return managerInfo;
    }

    public String departmentHeaderInfo() {
        return departmentHeaderInfo;
    }

    public String customInfo() {
        return customInfo;
    }

    @Override
    public String toString() {
        return "Request [name=" + name + ", reason=" + reason + ", days="
                + days + ",customInfo=" + customInfo + ", groupLeaderInfo="
                + groupLeaderInfo + ", managerInfo=" + managerInfo
                + ", departmentHeaderInfo=" + departmentHeaderInfo + "]";
    }

}
package myDesignPatternsTest.responsibleModel;

/**
 * 处理结果
 */
public class Result {
    public Boolean isRatify;
    public String  info;

    public Result(Boolean isRatify, String info) {
        this.isRatify = isRatify;
        this.info = info;
    }

    @Override
    public String toString() {
        return "Result{" +
                "isRatify=" + isRatify +
                ", info='" + info + '\'' +
                '}';
    }
}
package myDesignPatternsTest.responsibleModel;

/**
 * 处理请求的接口
 */
public interface Ratify {
    //处理请求
    public Result deal(Chain chain);

    interface  Chain{
        //获取当前请求
        Request Request();
        //转发请求
        Result proceed(Request request);
    }


}

看到上面的接口,可能会有人迷惑:在接口Ratify中为什么又定义一个Chain接口呢?其实这个接口是单独定义还是内部接口没有太大关系,但是考虑到Chain接口与Ratify接口的关系为提高内聚性就定义为内部接口了。定义Ratify接口是为了处理Request那为什么还要定义Chain接口呢?这正是责任链接口的精髓之处:转发功能及可动态扩展“责任人”,这个接口中定义了两个方法一个是request()就是为了获取request,如果当前Ratify的实现类获取到request之后发现自己不能处理或者说自己只能处理部分请求,那么他将自己的那部分能处理的就处理掉,然后重新构建一个或者直接转发Request给下一个责任人。可能这点说的不容易理解,我举个例子,在Android与后台交互中如果使用了Http协议,当然我们可能使用各种Http框架如HttpClient、OKHttp等,我们只需要发送要请求的参数就直接等待结果了,这个过程中你可能并没有构建请求头,那么框架帮你把这部分工作给做了,它做的工程中如果使用了责任链模式的话,它肯定会将Request进行包装(也就是添加请求头)成新的Request,我们姑且加他为Request1,如果你又希望Http做本地缓存,那么Request1又会被转发到并且重新进一步包装为Request2。总之Chain这个接口就是起到对Request进行重新包装的并将包装后的Request进行下一步转发的作用。如果还不是很明白也没关系,本实例会演示这一功能机制。

    ③上面说Chain是用来对Request重新包装以及将包装后的Request进行下一步转发用的,那我们就具体实现一下:

package myDesignPatternsTest.responsibleModel;

import java.util.List;

public class RealChain implements Ratify.Chain {
    public Request request;
    public List<Ratify> ratifyList;
    public int index;

    /**
     * 构造方法
     *
     * @param ratifyList
     *            Ratify接口的实现类集合
     * @param request
     *            具体的请求Request实例
     * @param index
     *            已经处理过该request的责任人数量
     */
    public RealChain(List<Ratify> ratifyList, Request request, int index) {
        this.ratifyList = ratifyList;
        this.request = request;
        this.index = index;
    }

    /**
     *  把请求传下去
     * @return
     */
    public Request Request() {
        return request;
    }

    /**
     * 请求转发类
     * @param request
     * @return
     */
    public Result proceed(Request request) {
        Result proceed=null;
        if (ratifyList.size() > index){
            RealChain realChain = new RealChain(ratifyList, request, index + 1);
            Ratify ratify = ratifyList.get(index);
            proceed = ratify.deal(realChain);
        }
        return proceed;
    }
}
package myDesignPatternsTest.responsibleModel;

public class DepartmentHeader implements  Ratify {
    public Result deal(Chain chain) {
        Request request = chain.Request();
        System.out.println("DepartmentHeader=====>request:"
                + request.toString());
        if (request.days() > 7) {
            return new Result(false, "你这个完全没必要");
        }
        return new Result(true, "DepartmentHeader:不要着急,把事情处理完再回来!");
    }

}
package myDesignPatternsTest.responsibleModel;

public class GroupLeader implements Ratify {
    @Override
    public Result deal(Chain chain) {
        Request Request=chain.Request();
        System.out.println("GroupLeader=========>request:"+Request.toString());
        if (Request.days() > 1) {
            // 包装新的Request对象
            Request newRequest = new Request.Builder().newRequest(Request)
                    .setManagerInfo(Request.name() + "平时表现不错,而且现在项目也不忙")
                    .build();
            return chain.proceed(newRequest);
        }
        return new Result(true, "GroupLeader:早去早回");
    }
}
package myDesignPatternsTest.responsibleModel;

public class Manager implements Ratify {
    @Override
    public Result deal(Chain chain) {
        Request request = chain.Request();
        System.out.println("Manager=====>request:" + request.toString());
        if (request.days() > 3) {
            // 构建新的Request
            Request newRequest = new Request.Builder().newRequest(request)
                    .setManagerInfo(request.name() + "每月的KPI考核还不错,可以批准")
                    .build();
            return chain.proceed(newRequest);

        }
        return new Result(true, "Manager:早点把事情办完,项目离不开你");
    }

}
package myDesignPatternsTest.responsibleModel;

import java.util.ArrayList;

/**
 * 责任链工具类
 */
public class ChainOfResponsibilityClient {
    private ArrayList<Ratify> ratifies;

    public ChainOfResponsibilityClient() {
        ratifies = new ArrayList<Ratify>();
    }

    /**
     * 方法描述:为了展示“责任链模式”的真正的迷人之处(可扩展性),在这里构造该方法以便添加自定义的“责任人”
     *
     * @param ratify
     */
    public void addRatifys(Ratify ratify) {
        ratifies.add(ratify);
    }

    /**
     * 方法描述:执行请求
     *
     * @param request
     * @return
     */
    public Result execute(Request request) {
        ArrayList<Ratify> arrayList = new ArrayList<Ratify>();
        arrayList.addAll(ratifies);
        arrayList.add(new GroupLeader());
        arrayList.add(new Manager());
        arrayList.add(new DepartmentHeader());

        RealChain realChain = new RealChain( arrayList, request, 0);
        return realChain.proceed(request);
    }

}
package myDesignPatternsTest.responsibleModel;

public class Client {
    public static void main(String[] args) {
        Request request = new Request.Builder().setName("张三").setDays(5)
                .setReason("事假").build();
        ChainOfResponsibilityClient client = new ChainOfResponsibilityClient();
        Result result = client.execute(request);

        System.out.println("结果:" + result.toString());

    }
}

刚开始就提到这个责任链模式是可以“动态扩展的”,我们验证一下,首先自定义一个“责任人”(其实也可以叫拦截器):

package myDesignPatternsTest.responsibleModel;

public class Custom implements  Ratify {
    public Result deal(Chain chain) {
        Request request = chain.Request();
        System.out.println("CustomInterceptor=>" + request.toString());
        String reason = request.reason();
        if (reason != null && reason.equals("事假")) {
            Request newRequest = new Request.Builder().newRequest(request)
                    .setCustomInfo(request.name() + "请的是事假,而且很着急,请领导重视一下")
                    .build();
            System.out.println("CustomInterceptor=>转发请求");
            return chain.proceed(newRequest);
        }
        return new Result(true, "同意请假");
    }

}
package myDesignPatternsTest.responsibleModel;

import java.util.ArrayList;

/**
 * 责任链工具类
 */
public class ChainOfResponsibilityClient {
    private ArrayList<Ratify> ratifies;

    public ChainOfResponsibilityClient() {
        ratifies = new ArrayList<Ratify>();
    }

    /**
     * 方法描述:为了展示“责任链模式”的真正的迷人之处(可扩展性),在这里构造该方法以便添加自定义的“责任人”
     *
     * @param ratify
     */
    public void addRatifys(Ratify ratify) {
        ratifies.add(ratify);
    }

    /**
     * 方法描述:执行请求
     *
     * @param request
     * @return
     */
    public Result execute(Request request) {
        ArrayList<Ratify> arrayList = new ArrayList<Ratify>();
        arrayList.addAll(ratifies);
        arrayList.add(new Custom());//新加的
        arrayList.add(new GroupLeader());
        arrayList.add(new Manager());
        arrayList.add(new DepartmentHeader());

        RealChain realChain = new RealChain( arrayList, request, 0);
        return realChain.proceed(request);
    }

}

 

customInterceptor=>Request [name=张三, reason=事假, days=5,customInfo=null, groupLeaderInfo=null, managerInfo=null, departmentHeaderInfo=null]
CustomInterceptor=>转发请求
GroupLeader=========>request:Request [name=张三, reason=事假, days=5,customInfo=张三请的是事假,而且很着急,请领导重视一下, groupLeaderInfo=null, managerInfo=null, departmentHeaderInfo=null]
Manager=====>request:Request [name=张三, reason=事假, days=5,customInfo=张三请的是事假,而且很着急,请领导重视一下, groupLeaderInfo=null, managerInfo=张三平时表现不错,而且现在项目也不忙, departmentHeaderInfo=null]
DepartmentHeader=====>request:Request [name=张三, reason=事假, days=5,customInfo=张三请的是事假,而且很着急,请领导重视一下, groupLeaderInfo=null, managerInfo=张三每月的KPI考核还不错,可以批准, departmentHeaderInfo=null]
结果:Result{isRatify=true, info='DepartmentHeader:不要着急,把事情处理完再回来!'}

责任链模式适用的情况

  1. 系统中已经有一个由处理者组成的链,这个链可能由复合模式给出
  2. 当有多于一个的处理者对象处理一个请求,而且事先并不知道到底由哪一个处理者对象处理一个请求,这个处理者是动态决定的
  3. 当系统想发出一个请求给多个处理者对象中的某一个,但是不明显指定是哪一个处理者对象会处理这个请求
  4. 当处理一个请求的处理者对象集合需要动态的指定时

 

这个模式不是特别理解,过段时间再来补充