责任链模式是一种对象行为模式,责任链模式使得有多个对象都有机会处理请求,从而避免请求的发送者和接收者之间之间的耦合关系,将这些对象连成一条链,并沿着这条链逐步传递该请求,直到有一个对象处理它为止。
在生活中我们会遇到很多关于责任链模式的情景,举个例子,A上班生病了需要请假,如果只请3天加则只需要小组长同意即可处理,如果需要请一个星期则可能需要部门经理处理,如果需要请假一个月那么则需要总经理来处理。这个处理流程基本上是根据权限的不同逐步往上申请汇报处理该请假请求的,这个就可以看作是一个责任链模式的情景,
从图中可以看出责任链模式总共包含两类角色:
抽象处理者角色(Handler):抽象处理者角色定义了处理请求的接口,同时还可以定义一个后继链角色。
具体处理者角色(ConcreteHandler):具体处理者角色处理他可以处理的请求,同时还可以访问它的后继者,如果该对象不能处理该请求就把该请求传递给它的后继者。
责任链模式适用于有多个对象可以处理一个请求,哪个对象能够处理该请求在运行的时刻确定。
客户端想在不明确指定具体的接收者的情况下,向多个对象中的一个提交一个请求。
可处理一个请求的对象集合可以动态的指定
责任链的示例我们就用本文开头说的场景来展示责任链模式的基本使用
首先定义一个抽象处理类
public abstract class Handler { protected Handler handler; public Handler(Handler handler) { this.handler = handler; } public abstract void handlerForLeave(String name,int days); }
其次分别定义小组长、部门领导、总经理对请假事宜的处理逻辑:
首先是小组长
public class LeaderHandler extends Handler{ public LeaderHandler(Handler handler) { super(handler); } @Override public void handlerForLeave(String name,int days) { if (name.equals("张三")){ if (days<=3){ System.out.println("同意"+name+"的请假申请,批准休假"+days+"天"); }else { System.out.println("leader无法处理该申请,将该申请传递给上级"); handler.handlerForLeave(name,days); } }else { /*其他处理逻辑*/ } } }
接下来是部门经理:
public class DeptManagerHandler extends Handler { public DeptManagerHandler(Handler handler) { super(handler); } @Override public void handlerForLeave(String name, int days) { if (name.equals("张三")){ if (days<=7){ System.out.println("同意"+name+"的请假申请,批准休假"+days+"天"); }else { System.out.println("DeptManager无法处理该申请,将该申请传递给上级"); handler.handlerForLeave(name,days); } }else { /*其他处理逻辑*/ } } }
最后是总经理
public class GeneralManagerHandler extends Handler { public GeneralManagerHandler(Handler handler) { super(handler); } @Override public void handlerForLeave(String name, int days) { if (name.equals("张三")){ if (days<=30){ System.out.println("同意"+name+"的请假申请,批准休假"+days+"天"); }else { System.out.println("不同意"); } }else { /*其他处理逻辑*/ } } }
然后通过客户端调用 以请假10天为例。
public class Client { public static void main(String[] args) { GeneralManagerHandler generalManagerHandler = new GeneralManagerHandler(null); DeptManagerHandler deptManagerHandler = new DeptManagerHandler(generalManagerHandler); LeaderHandler leaderHandler = new LeaderHandler(deptManagerHandler); leaderHandler.handlerForLeave("张三", 10); } } /* 运行结果: eader无法处理该申请,将该申请传递给上级 DeptManager无法处理该申请,将该申请传递给上级 同意张三的请假申请,批准休假10天*/
从上述例子我们可以看到责任链模式是如何实现基本使用的,但是上述例子有一个小问题,就是整个请假流程的调用与顺序,全部都是在客户端调用的时候就确定了,同时确定了首位处理者的信息,这样如果新增处理者是不是要改动客户端代码,或者说修改首位处理者也需要修改客户端代码,这样是不是对客户端还是不够友好呢?
下面有一个对该例子的一个升级版,能够完全的解耦客户端与具体处理逻辑直接的例子,这个例子的逻辑思想是基于Servlet中的Filter中的责任链模式逻辑。
针对Handler类和LeaderHandler、DeptManagerHandler、GeneralManagerHandler类有一些细微的改动具体如下
public interface Handler { public abstract void handlerForLeave(String name,int days, HandlerChain handlerChain); }
public class LeaderHandler implements Handler { @Override public void handlerForLeave(String name, int days, HandlerChain handlerChain) { if (name.equals("张三")) { if (days <= 3) { System.out.println("同意" + name + "的请假申请,批准休假" + days + "天"); return; } else { System.out.println("leader无法处理该申请,将该申请传递给上级"); handlerChain.handlerForLeave(name, days, handlerChain); } } else { /*其他处理逻辑*/ } } }
public class DeptManagerHandler implements Handler { @Override public void handlerForLeave(String name, int days, HandlerChain handlerChain) { if (name.equals("张三")) { if (days <= 7) { System.out.println("同意" + name + "的请假申请,批准休假" + days + "天"); return; } else { System.out.println(" DeptManager无法处理该申请,将该申请传递给上级"); handlerChain.handlerForLeave(name, days, handlerChain); } } else { /*其他处理逻辑*/ } } }
public class GeneralManagerHandler implements Handler { @Override public void handlerForLeave(String name, int days, HandlerChain handlerChain) { if (name.equals("张三")){ if (days<=30){ System.out.println("同意"+name+"的请假申请,批准休假"+days+"天"); }else { System.out.println("不同意"); } }else { /*其他处理逻辑*/ } return; } }
在此基础上增加了一个HandlerChain的类来保存具体请求处理类和请求处理类的顺序,同时也以HandlerChain类的handlerForLeave方法作为一个通用的请求处理的开头,这样在客户端调用的时候不会因为请求处理的逻辑 顺序的改动而做其他的一些改动,在本例中将HandlerChain类中的handlerList在客户端初始化,实际调用中可以将客户端初始化的过程放到配置文件这样对责任链中任何一环的修改只需要修改配置文件即可。
public class HandlerChain implements Handler { private int sizeCount = 0; private List<Handler> handlerList; public void addHandler(Handler handler) { if (handlerList == null) { handlerList = new ArrayList<Handler>(); } handlerList.add(handler); } @Override public void handlerForLeave(String name, int days,HandlerChain handlerChain) { if (sizeCount == handlerList.size()) { return; } handlerList.get(sizeCount++).handlerForLeave(name, days,handlerChain); } }
客户端调用如下:
public class Client { public static void main(String[] args) { GeneralManagerHandler generalManagerHandler = new GeneralManagerHandler(); DeptManagerHandler deptManagerHandler = new DeptManagerHandler(); LeaderHandler leaderHandler = new LeaderHandler(); HandlerChain handlerChain = new HandlerChain(); handlerChain.addHandler(leaderHandler); handlerChain.addHandler(deptManagerHandler); handlerChain.addHandler(generalManagerHandler); handlerChain.handlerForLeave("张三", 10, handlerChain); } } /*运行结果: leader无法处理该申请,将该申请传递给上级 DeptManager无法处理该申请,将该申请传递给上级 同意张三的请假申请,批准休假10天*/
首先,责任链模式实现了请求的请求者和处理者的松耦合,各自的业务逻辑变动不会影响到对方,其次在责任链中新增、删除、修改任何一环是不会影响到整个责任链的处理过程的,最后责任链中任何一环的职责独立,请求处理的逻辑也独立互不依赖。
原文:https://www.cnblogs.com/rhodesis/p/11273757.html