概述

在现实生活中,常常会出现这样的事例:一个请求有多个对象可以处理,但每个对象的处理条件或权限不同。例如,公司员工请假,可批假的领导有部门负责人、副总经理、总经理等,但每个领导能批准的天数不同,员工必须根据自己要请假的天数去找不同的领导签名,也就是说员工必须记住每个领导的姓名、电话和地址等信息,这增加了难度。这样的例子还有很多,如找领导出差报销、生活中的“击鼓传花“游戏等。

定义:

又名职责链模式,为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一对像记住其下一个对像的引用而连成条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。

结构

责任链模式主要包含以下角色:

  • 抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继链接
  • 具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给他的后继者
  • 客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,他不关心处理细节和请求的传递过程

案例实现

现需要开发一个请假流程控制系统,请假一天以下的假只需要小组长同意即可,一到三天还需部门经理同意,请求三到七天还要总经理同意

类图如下

 

 

 代码如下

//请假条类
@AllArgsConstructor
@Getter
public class LeaveRequest {

    //姓名
    private String name;

    //请假天数
    private int num;

    //请假内容
    private String content;

}

 

 

//抽象处理者类
public abstract class Handler {

    protected final static int NUM_ONE = 1;

    protected final static int NUM_THREE = 3;

    protected final static int NUM_SEVNE = 7;

    //该部门处理的请假天数区间
    private int numStart;

    private int numEnd;

    //声明后继者
    private Handler nextHandler;

    public Handler(int numStart, int numEnd) {
        this.numStart = numStart;
        this.numEnd = numEnd;
    }

    //设置上级领导对象
    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }

    //各级领导处理请假条的方法
    protected abstract void handlerLeave(LeaveRequest leave);

    //提交请求条
    public final void submit(LeaveRequest leave) {
        //该领导先进行审批
        this.handlerLeave(leave);
        if (this.nextHandler != null && leave.getNum() > this.numEnd) {
            //提交给上级领导
            this.nextHandler.submit(leave);
        }else {
            System.out.println("流程结束!");
        }

    }

}

 

 

//小组长类
public class GroupLeader extends Handler{

    public GroupLeader() {
        super(0, Handler.NUM_ONE);//使用父类,之后更改权限只需改父类即可
    }

    @Override
    protected void handlerLeave(LeaveRequest leave) {
        System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent());
        System.out.println("小组长审批:同意!");
    }
}
class Manager extends Handler{

    public Manager() {
        super(Handler.NUM_ONE, Handler.NUM_THREE);
    }

    @Override
    protected void handlerLeave(LeaveRequest leave) {
        System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent());
        System.out.println("部门经理审批:同意!");
    }
}

class GeneralManager extends Handler{

    public GeneralManager() {
        super(Handler.NUM_THREE, Handler.NUM_SEVNE);
    }

    @Override
    protected void handlerLeave(LeaveRequest leave) {
        System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent());
        System.out.println("总经理审批:同意!");
    }
}

 

 

public static void main(String[] args) {
        //创建请假条对象
        LeaveRequest leaveRequest = new LeaveRequest("小明",2,"身体不适");

        //创建各级领导对象
        GroupLeader groupLeader = new GroupLeader();
        Manager manager = new Manager();
        GeneralManager generalManager = new GeneralManager();

        //设置处理者链
        groupLeader.setNextHandler(manager);
        manager.setNextHandler(generalManager);

        //小明提交请假申请
        groupLeader.submit(leaveRequest);
    }

 

输出结果

 

 

 

优缺点

优点

  • 降低了对象之间的耦合度,该模式降低了请求发送者和接受者的耦合度
  • 增强了系统的可拓展性,可以根据需要增加新的请求处理类,满足开闭原则
  • 增强了给对象指派职责的灵活性,当工作流程发生变化,可以动态的改变链内的成员或者修改他们的次序,也可以动态的新增或者删除责任
  • 责任链简化了对象之间的链接,一个对象只需要保持一个指向其后继者的引用,不需保持其他所有处理者的引用,明确各类的责任范围,符合类的单一职责原则

缺点

  • 不能保证每个请求一定被处理,由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理
  • 对于较长的责任链,请求的处理可能涉及多个处理对象,系统性能收到一定的影响。
  • 责任链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于责任链的错误设置而导致系统出错,如可能会造成循环调用

 

源码解析

在javaWeb应用开发中,FilterChain是责任链模式的典型应用,以下是Filter的模拟实现分析

  • 模拟web请求Request以及web响应Response
public interface Request {
}

public interface Response {
}

 

  • 模拟web过滤器Filter
public interface Filter {

    public void doFilter(Request req, Response res, FilterChain c);
}

 

 

  • 模拟实现具体过滤器
public class FirsrFilter implements Filter {

    @Override
    public void doFilter(Request req, Response res, FilterChain c)  {
        System.out.println("过滤器1 前置处理");
        //先执行所有的Request在倒叙执行所有的response
        c.doFilter(req, res);
        System.out.println("过滤器1 后置处理");
    }

}

class SecondFilter implements Filter {

    @Override
    public void doFilter(Request req, Response res, FilterChain c)  {
        System.out.println("过滤器2 前置处理");
        //先执行所有的Request在倒叙执行所有的response
        c.doFilter(req, res);
        System.out.println("过滤器2 后置处理");
    }

}

 

 

  • 模拟实现过滤器链FilterChain
public class FilterChain {

    private List<Filter> filters = new ArrayList<>();
    private int index = 0;

    //链式调用
    public FilterChain addFilter(Filter filter) {
        this.filters.add(filter);
        return this;
    }

    public void doFilter(Request request, Response response) {
        if (index == filters.size()) {
            return;
        }
        Filter filter = filters.get(index);
        index++;
        filter.doFilter(request, response,this);

    }

}

 

 

  • 测试类
        Request req = null;

        Response res = null;
        FilterChain filterChain = new FilterChain();
        filterChain.addFilter(new FirsrFilter()).addFilter(new SecondFilter());
        filterChain.doFilter(req,res);

 

 

 

原文地址:http://www.cnblogs.com/lpzjava/p/16851573.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性