第一篇:浅析设计模式1 —— 工厂模式
第二篇:浅析设计模式2 —— 策略模式
第三篇:浅析设计模式3 —— 装饰者模式
第四篇:浅析设计模式4——模板方法模式
概述


下面从模式结构和使用步骤两个方面,简单阐述责任链方法模式的基本概念。
▐ 结构
|
|
|
|
|
|
|
|
|
|
|
|


使用示例
其实,大家平常接触到的各种审批流,就涉及多个审批节点,不同的审批节点负责人分别持有不同级别的审批权限。比如:请假审批流、紧急发布审批流、报销审批流等等。疫情管控时期,我们学校为了确保在校师生及其他员工的安全,会严格要求学生不能随意出入校门,如果有特殊情况如看病就医,则需在校务系统中进行申请,系统会根据学生请假出校的时长,设置不同级别的负责人进行严格审批。这一过程,用责任链模式就可以实现。
▐ 代码实现
// 创建抽象处理者类,定义指向下一节点的指针和抽象处理方法
public abstract class AbstractHandler {
private AbstractHandler next;
public void setNext(AbstractHandler next) {
this.next = next;
}
public AbstractHandler getNext() {
return next;
}
public abstract void handleRequest(int leaveDayNum);
}
// 定义具体处理者类1:系统自动审批
public class ConcreteHandler1 extends AbstractHandler {
public void handleRequest(int leaveDayNum) {
if (leaveDayNum <= 1) {
System.out.println("请假不超过" + leaveDayNum + "天" + ": 学校自动审批通过");
} else {
if (getNext() != null) {
getNext().handleRequest(leaveDayNum);
} else {
System.out.println("请假天数过长,需向学院提供签字承诺书");
}
}
}
}
// 定义具体处理中类2:导师审批
public class ConcreteHandler2 extends AbstractHandler {
public void handleRequest(int leaveDayNum) {
if (leaveDayNum <= 3) {
System.out.println("请假不超过" + leaveDayNum + "天" + ": 导师审批通过");
} else {
if (getNext() != null) {
getNext().handleRequest(leaveDayNum);
} else {
System.out.println("请假天数过长,需向学院提供签字承诺书");
}
}
}
}
// 定义具体处理者类3:辅导员审批
public class ConcreteHandler3 extends AbstractHandler {
public void handleRequest(int leaveDayNum) {
if (leaveDayNum <= 5) {
System.out.println("请假不超过" + leaveDayNum + "天" + ": 辅导员审批通过");
} else {
if (getNext() != null) {
getNext().handleRequest(leaveDayNum);
} else {
System.out.println("请假天数过长,需向学院提供签字承诺书");
}
}
}
}
// 定义具体处理者类4:院长审批
public class ConcreteHandler4 extends AbstractHandler {
public void handleRequest(int leaveDayNum) {
if (leaveDayNum <= 7) {
System.out.println("请假不超过" + leaveDayNum + "天" + ": 院长审批通过");
} else {
if (getNext() != null) {
getNext().handleRequest(leaveDayNum);
} else {
System.out.println("请假天数过长,需向学院提供签字承诺书");
}
}
}
}
//定义客户类:组装责任链,向链头节点发送请求
public class chainOfResponsibility {
public static void main(String[] args) {
AbstractHandler handler1 = new ConcreteHandler1();
AbstractHandler handler2 = new ConcreteHandler2();
AbstractHandler handler3 = new ConcreteHandler3();
AbstractHandler handler4 = new ConcreteHandler4();
handler1.setNext(handler2);
handler2.setNext(handler3);
handler3.setNext(handler4);
handler1.handleRequest(6);
}
}
请假不超过6天: 院长审批通过
扩展
纯的职责链模式:一个请求必须被某一个处理者对象所接收,且一个具体处理者对 某个请求的处理只能采用以下两种行为之一:自己处理(承担责任);把责任推给下一个具体处理者处理。
源码赏析

public interface Filter {
public default void init(FilterConfig filterConfig) throws ServletException {}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException;
public default void destroy() {}
}
// FilterChain
public interface FilterChain {
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException;
}
// ApplicationFilterChain
public final class ApplicationFilterChain implements FilterChain {
// 处理器链路,ApplicationFilterConfig 可以理解为对 Filter 的包装
private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];
// 当前处理器在链路中的索引
private int pos = 0;
// 调用入口
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
if( Globals.IS_SECURITY_ENABLED ) {
final ServletRequest req = request;
final ServletResponse res = response;
try {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedExceptionAction<Void>() {
public Void run()
throws ServletException, IOException {
// here
internalDoFilter(req,res);
return null;
}
}
);
} catch( PrivilegedActionException pe) {
Exception e = pe.getException();
if (e instanceof ServletException)
throw (ServletException) e;
else if (e instanceof IOException)
throw (IOException) e;
else if (e instanceof RuntimeException)
throw (RuntimeException) e;
else
throw new ServletException(e.getMessage(), e);
}
} else {
// here
internalDoFilter(request,response);
}
}
// 开始处理
private void internalDoFilter(ServletRequest request,
ServletResponse response)
throws IOException, ServletException {
// 不停的驱动下一个过滤器
if (pos < n) {
ApplicationFilterConfig filterConfig = filters[pos++];
try {
Filter filter = filterConfig.getFilter();
if (request.isAsyncSupported() && "false".equalsIgnoreCase(
filterConfig.getFilterDef().getAsyncSupported())) {
request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE);
}
if( Globals.IS_SECURITY_ENABLED ) {
final ServletRequest req = request;
final ServletResponse res = response;
Principal principal =
((HttpServletRequest) req).getUserPrincipal();
Object[] args = new Object[]{req, res, this};
SecurityUtil.doAsPrivilege ("doFilter", filter, classType, args, principal);
} else {
// 驱动过滤器
filter.doFilter(request, response, this);
}
} catch (IOException | ServletException | RuntimeException e) {
throw e;
} catch (Throwable e) {
e = ExceptionUtils.unwrapInvocationTargetException(e);
ExceptionUtils.handleThrowable(e);
throw new ServletException(sm.getString("filterChain.filter"), e);
}
return;
}
// 链路中没有更多过滤器了,开始进入 servlet
try {
if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
lastServicedRequest.set(request);
lastServicedResponse.set(response);
}
if (request.isAsyncSupported() && !servletSupportsAsync) {
request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR,
Boolean.FALSE);
}
if ((request instanceof HttpServletRequest) &&
(response instanceof HttpServletResponse) &&
Globals.IS_SECURITY_ENABLED ) {
final ServletRequest req = request;
final ServletResponse res = response;
Principal principal =
((HttpServletRequest) req).getUserPrincipal();
Object[] args = new Object[]{req, res};
SecurityUtil.doAsPrivilege("service",
servlet,
classTypeUsedInService,
args,
principal);
} else {
// 进入servlet 处理实际业务
servlet.service(request, response);
}
} catch (IOException | ServletException | RuntimeException e) {
throw e;
} catch (Throwable e) {
e = ExceptionUtils.unwrapInvocationTargetException(e);
ExceptionUtils.handleThrowable(e);
throw new ServletException(sm.getString("filterChain.servlet"), e);
} finally {
if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
lastServicedRequest.set(null);
lastServicedResponse.set(null);
}
}
}
}
-
降低对象之间的耦合度。 一个节点对象无须关心链的结构、到底是哪一个对象处理其请求,发送者和接收者也无须拥有对方的明确信息。 -
增强系统的可扩展性。 可以根据需要增加新的请求处理类,满足开闭原则。 -
灵活地为对象指派职责。 当工作流程变化时,可动态改变节点或调动节点次序,也可动态增删节点。 -
简化节点之间的连接。 各节点只需保持一个指向其后继者的引用,避免使用众多 if 或 if…else 语句。 -
责任分担,符合类的单一职责原则。 每个节点类只需处理自己该处理的工作,不该处理的传递给下一个节点类完成,各类的责任范围非常明确。
不能保证每个请求一定被处理。一个请求没有明确的接收者,可能一直传到链的末端都得不到处理。 当责任链太长时,一个请求可能需要涉及多个处理者,系统性能会受到一定影响。
责任链建立的合理性需要由客户端来保证,增加了客户端的复杂性,也可能会因为错误设置而导致系统陷入死循环。
在运行时需要动态使用多个关联对象来处理同一次请求时。比如,请假流程、员工入职流程、编译打包发布上线流程等。 不想让使用者知道具体的处理逻辑时。比如,做权限校验的登录拦截器。
需要动态更换处理对象时。比如,工单处理系统、网关 API 过滤规则系统等。
职责链模式常被用在框架开发中,实现过滤器、拦截器等功能,使用者可以在不修改源码的情况下,添加新的过滤拦截功能。
团队介绍
本文分享自微信公众号 - 大淘宝技术(AlibabaMTT)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。