一、基本介绍 责任链(Chain of Responsibility)模式 ,也叫职责链模式,属于行为型模式。== 该模式为请求创建了一个接收者对象的链,通常链中每个接收者都包含对另一个接收者的引用。== 当请求发生时,请求沿着这条链发送传递,链中的接收者接收到请求之后,可根据自己的职责,处理请求中相应的业务,处理完成后并将请求传递给链上的下一个接收者,直到这条链走完处理掉所有的业务为止。
二、责任链模式的实现 2.1、职责链模式中的主要角色及职责 职责链模式主要包含以下角色
抽象处理者(Handler)角色 :该角色一般是一个抽象类,类中声明了所有处理者用于请求处理的通用接口,以及指向下一个处理者的引用。具体处理者(Concrete Handler)角色 :该角色是一般是抽象处理者(抽象类)的子类,它实现了抽象处理者的处理方法,包含了实际的请求处理代码,用于处理请求中它自己负责的业务,并可以访问它的后继处理者。如果可以处理当前请求,则处理,否则就将该请求交给后继者去处理,从而形成一个职责链。客户端(Client)角色 :创建责任链,并向链上的任意一个处理者对象提交请求,它不关心处理细节和请求的传递过程。2.2、责任链模式结构 三、责任链模式的应用 3.1、责任链模式解决问题案例 :chestnut: 模拟某公司请假审批流程模块,流程如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 graph LR S((开始)) A(申请人) B(主任) C(部门经理) D(人力资源部经理) E(主管领导) F(申请人查阅) G(知会考勤管理员) P((结束)) S --> A --普通员工--> B --> C subgraph 请假天数大于3时需要人力资源部经理和主管领导额外审批 C --请假天数<=3--> F C --请假天数>3--> D --> E --> F end F --> G --> P
3.1.1、定义抽象处理者(Handler)角色 LeaderHandler 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public abstract class LeaderHandler { private LeaderHandler nextLeader; protected String name; public LeaderHandler (String name) { this .name = name; } public LeaderHandler getNextLeader () { return nextLeader; } public void setNextLeader (LeaderHandler nextLeader) { this .nextLeader = nextLeader; } public abstract void approval (Integer days) ; }
3.1.2、定义具体处理者(Concrete Handler)角色 DirectorHandler 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class DirectorHandler extends LeaderHandler { public DirectorHandler (String name) { super (name); } @Override public void approval (Integer days) { System.out.println("--->请假" + days + "天,由" + this .name + "审批通过--->" ); LeaderHandler nextLeader = super .getNextLeader(); if (null != nextLeader) { nextLeader.approval(days); } } }
DepartmentManagerHandler 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class DepartmentManagerHandler extends LeaderHandler { public DepartmentManagerHandler (String name) { super (name); } @Override public void approval (Integer days) { System.out.println("--->请假" + days + "天,由" + this .name + "审批通过--->" ); LeaderHandler nextLeader = super .getNextLeader(); if (null != nextLeader) { nextLeader.approval(days); } } }
ResourcesManagerHandler 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public class ResourcesManagerHandler extends LeaderHandler { public ResourcesManagerHandler (String name) { super (name); } @Override public void approval (Integer days) { if (days > 3 ) { System.out.println("--->请假" + days + "天,超过3天,由" + this .name + "审批通过--->" ); } LeaderHandler nextLeader = super .getNextLeader(); if (null != nextLeader) { nextLeader.approval(days); } } }
CompetentLeaderHandler 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public class CompetentLeaderHandler extends LeaderHandler { public CompetentLeaderHandler (String name) { super (name); } @Override public void approval (Integer days) { if (days > 3 ) { System.out.println("--->请假" + days + "天,超过3天,由" + this .name + "审批通过--->" ); } LeaderHandler nextLeader = super .getNextLeader(); if (null != nextLeader) { nextLeader.approval(days); } } }
3.1.3、定义客户端(Client)角色 Client 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class Client { public static void approvalTest (Integer days) { DirectorHandler directorHandler = new DirectorHandler ("部门侯主任" ); DepartmentManagerHandler departmentManagerHandler = new DepartmentManagerHandler ("部门吴经理" ); ResourcesManagerHandler resourcesManagerHandler = new ResourcesManagerHandler ("人力资源王经理" ); CompetentLeaderHandler competentLeaderHandler = new CompetentLeaderHandler ("主管领导老王" ); directorHandler.setNextLeader(departmentManagerHandler); departmentManagerHandler.setNextLeader(resourcesManagerHandler); resourcesManagerHandler.setNextLeader(competentLeaderHandler); directorHandler.approval(days); System.out.println("流程审批结束" ); } }
3.1.4、单元测试 ClientTest 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class ClientTest { @Test void clientTest () { System.out.println("Client call director" ); System.out.println("====================================" ); Client.approvalTest(2 ); System.out.println("====================================" ); Client.approvalTest(5 ); System.out.println("====================================" ); } }
测试结果:
3.2、责任链模式的应用 责任链模式在框架的开发中使用及其广泛,比如过滤器 (Interceptor) 和拦截器 (Interceptor),比如 Spring Interceptor 和 Servlet Filter
3.2.1、 Filter 和 Interceptor 责任链模式在框架的开发中使用及其广泛,比如 Spring Interceptor 拦截器和 Servlet Filter 过滤器。 Filter 抽象处理者角色,ApplicationFilterChain、VirtualFilterChain 等是责任链模式的具体实现类。 FilterChain 1 2 3 public interface FilterChain { void doFilter (ServletRequest var1, ServletResponse var2) throws IOException, ServletException; }
ApplicationFilterChain 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 public final class ApplicationFilterChain implements FilterChain { ... public void doFilter (ServletRequest request, ServletResponse response) throws IOException, ServletException { if (Globals.IS_SECURITY_ENABLED) { ServletRequest req = request; ServletResponse res = response; try { AccessController.doPrivileged(() -> { this .internalDoFilter(req, res); return null ; }); } catch (PrivilegedActionException var7) { Exception e = var7.getException(); if (e instanceof ServletException) { throw (ServletException)e; } if (e instanceof IOException) { throw (IOException)e; } if (e instanceof RuntimeException) { throw (RuntimeException)e; } throw new ServletException (e.getMessage(), e); } } else { this .internalDoFilter(request, response); } } ... }
HandlerInterceptor 抽象处理者角色,LocaleChangeInterceptor 等是责任链模式的具体实现类。HandlerInterceptor 1 2 3 4 5 6 7 public interface HandlerInterceptor { boolean preHandle (HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception; void postHandle (HttpServletRequest var1, HttpServletResponse var2, Object var3, ModelAndView var4) throws Exception; void afterCompletion (HttpServletRequest var1, HttpServletResponse var2, Object var3, Exception var4) throws Exception; }
LocaleChangeInterceptor 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public class LocaleChangeInterceptor extends HandlerInterceptorAdapter { ... public boolean preHandle (HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException { String newLocale = request.getParameter(this .getParamName()); if (newLocale != null && this .checkHttpMethod(request.getMethod())) { LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request); if (localeResolver == null ) { throw new IllegalStateException ("No LocaleResolver found: not in a DispatcherServlet request?" ); } try { localeResolver.setLocale(request, response, this .parseLocaleValue(newLocale)); } catch (IllegalArgumentException var7) { if (!this .isIgnoreInvalidLocale()) { throw var7; } this .logger.debug("Ignoring invalid locale value [" + newLocale + "]: " + var7.getMessage()); } } return true ; } ... }
3.2.1、 Activiti 工作流 Activit 整体上采用命令模式,同时搭配其对应的责任链来完成,它的各操作方法其底层基本都是以命令模式来实现,从而实现代码功能解耦,将流程引擎大部分涉及到客户端的需求业务交给外部以具体命令实现类的实现。
Command 命令接口,所有的具体命令都需要实现该类,最终业务就是执行该类的 execute 方法。 CommandContext 命令上下文,为具体命令的执行提供上下文支撑。 四、总结 附:本次演示的项目地址 https://github.com/syshlang/java-design-patterns