责任链设计模式(Chain of Responsibility Pattern)是一种行为设计模式,它旨在将请求的发送者和接收者解耦,让多个对象都有机会处理这个请求。在这种模式下,请求从一个对象传递到另一个对象,形成一条链,直到有一个对象处理这个请求为止。
核心组成
责任链模式主要包括以下几个核心组件:
- 处理器(Handler)接口:定义了处理请求的方法。所有具体处理器都需要实现这个接口。
- 具体处理器(Concrete Handler):实现处理器接口的类。它会尝试处理接收到的请求;如果能够处理,则进行处理;如果不能,则将请求转发给它的后继者。
- 客户端(Client):负责创建责任链,并向链上的某个处理器对象发起请求。
工作原理
- 客户端向责任链上的第一个处理器发送请求。
- 每个处理器接收到请求后,决定自己是否有能力进行处理。
- 如果可以,则该处理器会“消费”这个请求,完成相应操作。
- 如果不能,则将该请求转发给它在责任链中的后继者。
- 这个过程会一直持续下去,直到找到一个合适的处理器或者整条链都无法处理这个请求。
应用场景
责任链模式特别适用于以下情况:
- 有多个对象可以处理同一请求时,但具体由哪个对象来处理该请求在运行时才确定。
- 想在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
- 可以动态地指定一组对象来处理请求。
优缺点
优点
- 降低耦合度:它将请求的发送者和接收者解耦。
- 增强了系统灵活性:可以动态地添加或修改责任链上的成员。
- 增加了给对象指派职责的灵活性:通过改变链内成员或调整它们的顺序,允许动态地新增或删除责任。
缺点
- 性能问题:每一个请求都是从链头开始遍历直到找到合适的处理者。如果责任链很长,则可能影响性能。
- 调试困难:特别是在责任链较长、并且涉及到实时交互时,理解和调试责任链可能会比较复杂。
实现方式
链表实现
第一种实现方式如下所示。其中,Handler 是所有处理器类的抽象父类,handle() 是抽象方法。每个具体的处理器类(HandlerA、HandlerB)的 handle() 函数的代码结构类似,如果它能处理该请求,就不继续往下传递;如果不能处理,则交由后面的处理器来处理(也就是调用 successor.handle())。HandlerChain 是处理器链,从数据结构的角度来看,它就是一个记录了链头、链尾的链表。其中,记录链尾是为了方便添加处理器。
package xyz.xiaolinz.demo.chain.linked;
/**
* 责任链设计模式 - 链表方式实现
*
* 处理器接口
*
* @author huangmuhong
* @version 1.0.0
* @date 2024/02/20
*/
public interface Handler {
/**
* 处理
*
* @return boolean
* @author huangmuhong
* @date 2024/02/20
* @since 1.0.0
*/
boolean handle();
/**
* 获取下一个处理器
*
* @return {@link Handler }
* @date 2024/02/20
* @since 1.0.0
*/
Handler getNext();
/**
* 设置下一个处理器
*
* @param handler 下一个处理器
* @return void
* @date 2024/02/20
* @since 1.0.0
*/
void setNext(Handler handler);
}
package xyz.xiaolinz.demo.chain.linked;
/**
* @author huangmuhong
* @date 2024/2/20
*/
public abstract class AbstractHandler implements Handler {
private Handler next;
@Override
public Handler getNext() {
return next;
}
@Override
public void setNext(Handler handler) {
this.next = handler;
}
}
package xyz.xiaolinz.demo.chain.linked;
/**
* 责任链设计模式 - 链表实现
*
* 具体处理器
*
* @author huangmuhong
* @version 1.0.0
* @date 2024/02/20
* @see Handler
*/
public class AHandler extends AbstractHandler {
@Override
public boolean handle() {
System.out.println("AHandler handle");
boolean handled = false;
//...
if (!handled && getNext() != null) {
return getNext().handle();
}
return handled;
}
}
package xyz.xiaolinz.demo.chain.linked;
/**
* 责任链设计模式 - 链表实现
*
* 具体处理器
*
* @author huangmuhong
* @version 1.0.0
* @date 2024/02/20
* @see Handler
*/
public class BHandler extends AbstractHandler {
@Override
public boolean handle() {
System.out.println("BHandler handle");
boolean handled = false;
//...
if (!handled && getNext() != null) {
return getNext().handle();
}
return handled;
}
}
package xyz.xiaolinz.demo.chain.linked;
/**
* 处理器链
*
* @author huangmuhong
* @version 1.0.0
* @date 2024/02/20
*/
public class HandleChain {
private Handler head;
private Handler tail;
/**
* 添加处理程序
*
* @param handler 处理程序
* @author huangmuhong
* @date 2024/02/20
* @since 1.0.0
*/
public void addHandler(Handler handler) {
handler.setNext(null);
if (head == null) {
head = handler;
tail = handler;
return;
}
tail.setNext(handler);
tail = handler;
}
/**
* 处理
*
* @author huangmuhong
* @date 2024/02/20
* @since 1.0.0
*/
public void handle() {
if (head != null) {
head.handle();
}
}
}
package xyz.xiaolinz.demo.chain.linked;
/**
* @author huangmuhong
* @date 2024/2/20
*/
public class Main {
public static void main(String[] args) {
final HandleChain handleChain = new HandleChain();
handleChain.addHandler(new AHandler());
handleChain.addHandler(new BHandler());
handleChain.handle();
}
}
实际上,上面的代码实现不够优雅。处理器类的 handle() 函数,不仅包含自己的业务逻辑,还包含对下一个处理器的调用。
数组实现
这种实现方式更加简单。HandlerChain 类用数组而非链表来保存所有的处理器,并且需要在 HandlerChain 的 handle() 函数中,依次调用每个处理器的 handle() 函数。
package xyz.xiaolinz.demo.chain.array;
/**
* 责任链设计模式 - 链表方式实现
*
* 处理器接口
*
* @author huangmuhong
* @version 1.0.0
* @date 2024/02/20
*/
public interface Handler {
/**
* 处理
*
* @return boolean
* @author huangmuhong
* @date 2024/02/20
* @since 1.0.0
*/
boolean handle();
}
package xyz.xiaolinz.demo.chain.array;
/**
* @author huangmuhong
* @date 2024/2/20
*/
public class AHandler implements Handler {
@Override
public boolean handle() {
System.out.println("AHandler handle");
boolean handled = false;
//...
return handled;
}
}
package xyz.xiaolinz.demo.chain.array;
/**
* @author huangmuhong
* @date 2024/2/20
*/
public class BHandler implements Handler {
@Override
public boolean handle() {
System.out.println("BHandler handle");
boolean handled = false;
//...
return handled;
}
}
package xyz.xiaolinz.demo.chain.array;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* 手柄链
*
* @author huangmuhong
* @version 1.0.0
* @date 2024/02/20
*/
public class HandleChain {
private final List<Handler> handlers = new ArrayList<>();
public void addHandler(Handler... handlers) {
Collections.addAll(this.handlers, handlers);
}
/**
* 处理
*
* @return void
* @date 2024/02/20
* @since 1.0.0
*/
public void handle() {
for (Handler handler : handlers) {
if (handler.handle()) {
break;
}
}
}
}
package xyz.xiaolinz.demo.chain.array;
/**
* @author huangmuhong
* @date 2024/2/20
*/
public class Main {
public static void main(String[] args) {
final HandleChain handleChain = new HandleChain();
handleChain.addHandler(new AHandler());
handleChain.addHandler(new BHandler());
handleChain.handle();
}
}
特殊用法
在 GoF 给出的定义中,如果处理器链上的某个处理器能够处理这个请求,那就不会继续往下传递请求。实际上,职责链模式还有一种变体,那就是请求会被所有的处理器都处理一遍,不存在中途终止的情况。
根据上述描述,我们的责任链不会因为产生中间状态而停止调用下一个处理器,所以并不需要具体的返回值,所有的中间状态都可以通过入参进行统一的传递
数组实现
package xyz.xiaolinz.demo.chain.mutate.array;
/**
* 处理程序
*
* @author huangmuhong
* @version 1.0.0
* @date 2024/02/20
*/
public interface Handler {
/**
* 处理
*
* @author huangmuhong
* @date 2024/02/20
* @since 1.0.0
*/
void handle();
}
package xyz.xiaolinz.demo.chain.mutate.array;
/**
* @author huangmuhong
* @date 2024/2/20
*/
public class AHandler implements Handler {
@Override
public void handle() {
System.out.println("AHandler handle");
//...
}
}
package xyz.xiaolinz.demo.chain.mutate.array;
/**
* @author huangmuhong
* @date 2024/2/20
*/
public class BHandler implements Handler {
@Override
public void handle() {
System.out.println("BHandler handle");
//...
}
}
package xyz.xiaolinz.demo.chain.mutate.array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 处理链
*
* @author huangmuhong
* @version 1.0.0
* @date 2024/02/20
*/
public class HandlerChain {
private final List<Handler> handlers = new ArrayList<>();
public void addHandler(Handler... handlers) {
this.handlers.addAll(Arrays.asList(handlers));
}
public void handle() {
for (Handler handler : handlers) {
handler.handle();
}
}
}
package xyz.xiaolinz.demo.chain.mutate.array;
/**
* @author huangmuhong
* @date 2024/2/20
*/
public class Main {
public static void main(String[] args) {
final HandlerChain handleChain = new HandlerChain();
handleChain.addHandler(new AHandler());
handleChain.addHandler(new BHandler());
handleChain.handle();
}
}
递归实现
在平时的 servlet web工程中经常使用的过滤器Filter
其实也是基于责任链设计模式的思想设计的,他就是责任链中的变体,依次调用注册的过滤器直到所有过滤器调用或者抛出异常后才结束,我们可以参考他的源码
Servlet Filter 是 Java Servlet 规范中定义的组件,翻译成中文就是过滤器,它可以实现对 HTTP 请求的过滤功能,比如鉴权、限流、记录日志、验证参数等等。因为它是 Servlet 规范的一部分,所以,只要是支持 Servlet 的 Web 容器(比如,Tomcat、Jetty 等),都支持过滤器功能。为了帮助你理解,我画了一张示意图阐述它的工作原理,如下所示。
我们查看 Filter
接口的源码
package javax.servlet;
import java.io.IOException;
public interface Filter {
default void init(FilterConfig filterConfig) throws ServletException {
}
void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException;
default void destroy() {
}
}
可以看到,在具体需要实现的方法doFilter
中有一个FilterChain
属性,该属性是用来递归调用过滤器链的。
如何递归调用下一个过滤器:
package xyz.tiegangan.capability.platform.server.test.filter;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import java.io.IOException;
/**
* @author huangmuhong
* @date 2024/2/23
*/
public class TestFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
filterChain.doFilter(servletRequest, servletResponse);
}
}
我们可以通过FilterChain
接口的实现类ApplicationFilterChain
中查看到他具体的递归调用逻辑,以下是核心逻辑的代码片段。
/**
* Invoke the next filter in this chain, passing the specified request and response. If there are no more filters in
* this chain, invoke the <code>service()</code> method of the servlet itself.
*
* @param request The servlet request we are processing
* @param response The servlet response we are creating
*
* @exception IOException if an input/output error occurs
* @exception ServletException if a servlet exception occurs
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
// 当`Globals.IS_SECURITY_ENABLED`为`true`时,会执行一个特定的代码块,这段代码使用了Java的安全API来执行`internalDoFilter`方法。这是为了在Java的安全管理器启用的情况下,确保对`internalDoFilter`方法的调用是在一个受控的安全上下文中进行的。
if (Globals.IS_SECURITY_ENABLED) {
final ServletRequest req = request;
final ServletResponse res = response;
try {
java.security.AccessController.doPrivileged((java.security.PrivilegedExceptionAction<Void>) () -> {
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 {
// 调用过滤器
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();
// 如果请求支持异步处理,但过滤器不支持,设置请求属性ASYNC_SUPPORTED_ATTR为false
if (request.isAsyncSupported() &&
"false".equalsIgnoreCase(filterConfig.getFilterDef().getAsyncSupported())) {
request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE);
}
// 如果安全管理器启用,以特权方式执行过滤器的doFilter方法
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 {
// 普通方式执行过滤器的doFilter方法
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 {
// 如果dispatcherWrapsSameObject为true,记录当前请求和响应
if (dispatcherWrapsSameObject) {
lastServicedRequest.set(request);
lastServicedResponse.set(response);
}
// 如果请求支持异步处理,但Servlet不支持,设置请求属性ASYNC_SUPPORTED_ATTR为false
if (request.isAsyncSupported() && !servletSupportsAsync) {
request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE);
}
// 如果安全管理器启用,以特权方式执行Servlet的service方法
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的service方法
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 {
// 如果dispatcherWrapsSameObject为true,清除记录的请求和响应
if (dispatcherWrapsSameObject) {
lastServicedRequest.set(null);
lastServicedResponse.set(null);
}
}
}
我们模仿Filter
的思路,实现一个递归版本的责任链
- 定义一个
HandleChain
接口,这是我们的递归调度接口
package xyz.xiaolinz.demo.chain.mutate.recurve;
/**
* @author huangmuhong
* @date 2024/2/23
*/
public interface HandlerChain {
/**
* 处理
*
* @param context 上下文
* @author huangmuhong
* @date 2024/02/23
* @since 1.0.0
*/
void handle(Context context);
}
- 定义
Handler
接口,处理器角色
package xyz.xiaolinz.demo.chain.mutate.recurve;
/**
* 处理器
*
* @author huangmuhong
* @version 1.0.0
* @date 2024/02/23
*/
public interface Handler {
/**
* 处理
*
* @param context 上下文
* @param handlerChain 处理链
* @author huangmuhong
* @date 2024/02/23
* @since 1.0.0
*/
void handle(Context context, HandlerChain handlerChain);
/**
* 排序
*
* @return int
* @author huangmuhong
* @date 2024/02/23
* @since 1.0.0
*/
int order();
}
- 定义
HandlerChainHandle
类,用于实现链的调度与管理,并在内部实现HandlerChain
的具体逻辑
package xyz.xiaolinz.demo.chain.mutate.recurve;
import java.util.List;
/**
* 处理程序链处理程序
*
* @author huangmuhong
* @version 1.0.0
* @date 2024/02/23
*/
public class HandlerChainHandler {
private List<Handler> handlers;
public HandlerChainHandler(List<Handler> handlers) {
this.handlers = handlers;
}
/**
* 处理
*
* @author huangmuhong
* @date 2024/02/23
* @since 1.0.0
*/
public void handle(Context context) {
// 排序过滤器链
handlers.sort(Comparator.comparingInt(Handler::order));
// 递归调用
new DefaultHandlerChain(handlers).handle(context);
}
/**
* 默认处理程序链
*
* @author huangmuhong
* @version 1.0.0
* @date 2024/02/23
* @see HandlerChain
*/
static class DefaultHandlerChain implements HandlerChain {
private final List<Handler> handlers;
private int pos;
public DefaultHandlerChain(List<Handler> handlers) {
this.handlers = handlers;
this.pos = 0;
}
@Override
public void handle(Context context) {
if (pos < handlers.size()) {
Handler handler = handlers.get(pos++);
handler.handle(context, this);
}
}
}
}
- 定义几个默认的过滤器链实现
package xyz.xiaolinz.demo.chain.mutate.recurve;
/**
* @author huangmuhong
* @date 2024/2/23
*/
public class AHandler implements Handler {
@Override
public void handle(Context context, HandlerChain handlerChain) {
System.out.println("这里是AHandler,我将是第一个处理器,上下文中的数据是:" + context.getDesc());
handlerChain.handle(context);
}
@Override
public int order() {
return 1;
}
}
package xyz.xiaolinz.demo.chain.mutate.recurve;
/**
* @author huangmuhong
* @date 2024/2/23
*/
public class BHandler implements Handler {
@Override
public void handle(Context context, HandlerChain handlerChain) {
System.out.println("这里是BHandler,我将是第三个处理器,上下文中的数据是:" + context.getDesc());
handlerChain.handle(context);
}
@Override
public int order() {
return 3;
}
}
package xyz.xiaolinz.demo.chain.mutate.recurve;
/**
* @author huangmuhong
* @date 2024/2/23
*/
public class CHandler implements Handler {
@Override
public void handle(Context context, HandlerChain handlerChain) {
System.out.println("这里是CHandler,我将是第二个处理器,上下文中的数据是:" + context.getDesc());
handlerChain.handle(context);
}
@Override
public int order() {
return 2;
}
}
- 通过
HandlerChainHandler
动态的递归调用这些处理器
package xyz.xiaolinz.demo.chain.mutate.recurve;
import java.util.ArrayList;
/**
* @author huangmuhong
* @date 2024/2/23
*/
public class Main {
public static void main(String[] args) {
Context context = new Context();
context.setDesc("This is a context.");
final ArrayList<Handler> handlers = new ArrayList<>();
handlers.add(new AHandler());
handlers.add(new BHandler());
handlers.add(new CHandler());
final HandlerChainHandler handlerChainHandler = new HandlerChainHandler(handlers);
handlerChainHandler.handle(context);
}
}
结果:
评论区