责任链设计模式
1. 简单介绍
责任链模式(Chain of Responsibility)是一种行为型设计模式。该模式使得多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链(与链表结构类似),并沿着这条链传递该请求,直到有一个对象完成处理为止。
2. 使用场景
- 需要动态指定一组对象完成请求的处理
- 一个请求可以由多个对象进行处理,具体交由哪个对象处理由程序运行时自动确定
- 处理流(即处理链)需要动态的扩展
3. 场景举例
Servlet
中,过滤器的过滤流在设计上采用了责任链模式。 用户可以根据自身的需求,对过滤器链(FilterChain) 进行扩展,并定义过滤器的过滤顺序。当HTTP请求进入过滤器链后,该请求会按过滤器链的顺序对请求进行逐项过滤。对于不满足过滤条件的请求,则直接返回,不会对请求做具体的处理。
4. UML类图
5. 具体实现
描述
- 背景:土豆经过处理链(责任链)后变成美味的薯片
- CleanHandler:处理链中的一换,作用是清洗土豆
- SliceHandler:处理链中的一换,作用是对土豆进行切片
- CookHandler:处理链中的一换,作用是对土豆进行烹饪
- Client:客户端,负责去菜场买土豆
代码实现
Handler.java
/**
* 处理类顶层接口
*/
public interface Handler {
/**
* 设置后置处理类
*/
Handler setNextHandler(Handler handler);
/**
* 处理方法
*/
void handle(Potato potato);
}
CleanHandler.java
/**
* 清洗土豆处理类
*/
public class CleanHandler implements Handler {
private Handler nextHandler;
@Override
public Handler setNextHandler(Handler handler) {
this.nextHandler = handler;
return this;
}
@Override
public void handle(Potato potato) {
// 清洗土豆
System.out.println("清理土豆");
// 土豆变得干净
potato.clean = true;
if (nextHandler != null) {
nextHandler.handle(potato);
}
}
}
SliceHandler.java
/**
* 对土豆进行切片
*/
public class SliceHandler implements Handler {
private Handler nextHandler;
@Override
public Handler setNextHandler(Handler handler) {
this.nextHandler = handler;
return this;
}
@Override
public void handle(Potato potato) {
// 对土豆切片
System.out.println("土豆切片");
// 土豆形状变成片
potato.shape = "slice";
if (nextHandler != null) {
nextHandler.handle(potato);
}
}
}
CookHandler.java
/**
* 对土豆进行烹饪
*/
public class CookHandler implements Handler {
private Handler nextHandler;
@Override
public Handler setNextHandler(Handler handler) {
this.nextHandler = handler;
return this;
}
@Override
public void handle(Potato potato) {
// 油炸土豆片
System.out.println("油炸土豆片");
// 撒上番茄粉
System.out.println("撒上番茄粉");
// 土豆变得干净
potato.taste = "番茄味,嘎嘣脆";
if (nextHandler != null) {
nextHandler.handle(potato);
}
}
}
Potato.java
/**
* 土豆
*/
public class Potato {
/**
* 初始时的土豆是脏的
*/
protected boolean clean = false;
/**
* 初始时的土豆是圆的
*/
protected String shape = "round";
/**
* 初始时的土豆是没有味道的
*/
protected String taste = "无味的";
@Override
public String toString() {
return "Potato{" +
"clean=" + clean +
", shape='" + shape + '\'' +
", taste='" + taste + '\'' +
'}';
}
}
Client.java
/**
* 客户端
*/
public class Client {
public static void main(String[] args) {
Handler cleanHandler = new CleanHandler();
Handler sliceHandler = new SliceHandler();
Handler cookHandler = new CookHandler();
// 土豆清洗完后,进行切片
cleanHandler.setNextHandler(sliceHandler);
// 土豆切片后,进行油炸调味
sliceHandler.setNextHandler(cookHandler);
// 从菜场买来一个为处理的土豆
Potato potato = new Potato();
// 查看土豆状态
// 输出:Potato{clean=false, shape='round', taste='无味的'}
System.out.println(potato.toString());
// 把土豆交给责任链处理
cleanHandler.handle(potato);
// 查看处理完成后的土豆状态
// 输出:Potato{clean=true, shape='slice', taste='番茄味,嘎嘣脆'}
System.out.println(potato.toString());
}
}
7. 源码展示
SpringMVC
中的拦截器(Interceptor) 在对请求进行拦截过滤时,采用了责任链设计模式。使用SrpingMVC
框架时,用户可以根据自身需求定义多个拦截器。这些拦截器的引用都被HandlerExecutionChain中
的成员数组变量*HandlerInterceptor[ ]所持有。当浏览器发起请求到达前端控制器DispatcherServlet
时,由DispatcherServlet
将请求交给HandlerExecutionChain
进行拦截处理。与Gof提出的责任链模式不同的是,拦截器不再持有后置(即下一个)拦截器的引用,而是通过HandlerInterceptor[ ]*索引找出下一个拦截器。其中源码如下:
DispatcherServlet.java
public class DispatcherServlet extends FrameworkServlet {
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 持有所有拦截器的引用
HandlerExecutionChain mappedHandler = null;
try {
// 部分代码省略,只展示核心代码
// applyPreHandle方法,将请求进行前置拦截处理
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 请求的具体执行
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
// applyPostHandle方法,将请求进行后置拦截处理
mappedHandler.applyPostHandle(processedRequest, response, mv);
} catch (Exception var20) {
dispatchException = var20;
}
// 部分代码省略,只展示核心代码
}
}
}
HandlerExecutionChain.java
public class HandlerExecutionChain {
private HandlerInterceptor[] interceptors;
// 注入拦截器
public HandlerExecutionChain(Object handler, HandlerInterceptor... interceptors) {
this.interceptorIndex = -1;
if (handler instanceof HandlerExecutionChain) {
HandlerExecutionChain originalChain = (HandlerExecutionChain)handler;
this.handler = originalChain.getHandler();
this.interceptorList = new ArrayList();
CollectionUtils.mergeArrayIntoCollection(originalChain.getInterceptors(), this.interceptorList);
CollectionUtils.mergeArrayIntoCollection(interceptors, this.interceptorList);
} else {
this.handler = handler;
this.interceptors = interceptors;
}
}
// 拦截器链对请求进行前置拦截处理
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
HandlerInterceptor[] interceptors = this.getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
// 遍历所有拦截器
for(int i = 0; i < interceptors.length; this.interceptorIndex = i++) {
HandlerInterceptor interceptor = interceptors[i];
// 具体的拦截器对请求进行预处理
if (!interceptor.preHandle(request, response, this.handler)) {
this.triggerAfterCompletion(request, response, (Exception)null);
return false;
}
}
}
return true;
}
// 拦截器链对请求进行后置拦截处理
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
HandlerInterceptor[] interceptors = this.getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
// 遍历所有拦截器
for(int i = interceptors.length - 1; i >= 0; --i) {
HandlerInterceptor interceptor = interceptors[i];
// 具体的拦截器对响应进行后置处理
interceptor.postHandle(request, response, this.handler, mv);
}
}
}
}