责任链模式ChainofResponsibility
简单实现--实现链式调用以及调用链中断
interface Filter {
boolean doFilter(Msg m);
}
class HTMLFilter implements Filter {
@Override
public boolean doFilter(Msg m) {
String r = m.getMsg();
r = r.replace('<', '[');
r = r.replace('>', ']');
m.setMsg(r);
return true;
}
}
// ... 其他具体的过滤器实现类
调用链也实现Filter接口,是为了可以两个链子连起来。也就是说把后面的链子当做过滤器的List的最后一个元素。利用了多态,都实现了doFilter,但是具体的过滤器是具体的处理,FilterChain 的 doFilter是为了开始调用自己的链子。注意此时上一个还在栈里面,有点类似递归。
- add(Filter f) 返回 FilterChain ,是为了链式调用,注意add方法是只有FilterChain 有的,其他实现了Filter 的具体过滤器是没有这个方法的。
- doFilter(Msg m) :返回boolean 为了决定是否继续往下调用链子上面后面的调用器
class FilterChain implements Filter {
private List<Filter> filters = new ArrayList<>();
public FilterChain add(Filter f) {
filters.add(f);
return this;
}
public boolean doFilter(Msg m) {
for(Filter f : filters) {
// 精髓,利用返回的boolean决定还是否往下传递
if(!f.doFilter(m)) return false;
}
return true;
}
}
调用案例
FilterChain fc = new FilterChain();
fc.add(new HTMLFilter()).add(new SensitiveFilter());
FilterChain fc2 = new FilterChain();
fc2.add(new FaceFilter()).add(new URLFilter());
// 拼接前后两个调用链
fc.add(fc2);
fc.doFilter(msg);
Servlet的Filter
和上面直接在FilterChain里面遍历所有的Filter,调用doFilter不一样,为了实现req是abc顺序,resp是cba顺序,这里使用利用了递归的思想,不在FilterChain设置for循环,而是每一个具体的Filter都去调用FilterChain的doFilter,让FilterChain去调用下一个Filter,返回的时候其实就是递归返回,再执行后面的语句,也就是对resp操作,就相当于是栈,毕竟栈就是递归的具象。所以返回的时候顺序就反过来了。
- 具体的过滤器的doFilter实现:
<font style="color:#cc7832;">public boolean </font>``<font style="color:#ffc66d;">doFilter</font>``_(_``Request request``<font style="color:#cc7832;">, </font>``Response response``<font style="color:#cc7832;">, </font>``FilterChain chain``_)_- **内部自己处理之后调用Filter的doFilter方法来调用下一个filter **
- FilterChain的doFilter实现:
public void doFilter(Request request, Response response)- 内部直接调用链子里的下一个Filter
- 借助对象变量 index 标志当前运行到哪一个过滤器了
package com.deltaqin.designPattern.d10_chainOfResponsibility.servletFilter;
import java.util.ArrayList;
import java.util.List;
/**
* @author deltaqin
* @date 2021/3/27 12:39 下午
*/
public class ServletFilter {
public static void main(String[] args) {
Request request = new Request();
request.str = "大家好:),<script>,deltaqin ,大家都是996 ";
Response response = new Response();
response.str = "response";
FilterChain chain = new FilterChain();
chain.add(new HTMLFilter()).add(new SensitiveFilter());
chain.doFilter(request, response);
System.out.println(request.str);
System.out.println(response.str);
}
}
interface Filter {
void doFilter(Request request, Response response, FilterChain chain);
}
class HTMLFilter implements Filter {
@Override
public void doFilter(Request request, Response response, FilterChain chain) {
request.str = request.str.replaceAll("<", "[").replaceAll(">", "]") + "HTMLFilter()";
chain.doFilter(request, response);
response.str += "--HTMLFilter()";
}
}
class Request {
String str;
}
class Response {
String str;
}
class SensitiveFilter implements Filter {
@Override
public void doFilter(Request request, Response response, FilterChain chain) {
request.str = request.str.replaceAll("996", "955") + " SensitiveFilter()";
chain.doFilter(request, response);
response.str += "--SensitiveFilter()";
}
}
class FilterChain {
List<Filter> filters = new ArrayList<>();
int index = 0;
public FilterChain add(Filter f) {
filters.add(f);
return this;
}
public void doFilter(Request request, Response response) {
// 这里相当于是递归结束的条件,调用链里面的所有的需要调用的都调用过了,就返回
if(index == filters.size())
return;
// 否则继续调用下一个Filter
Filter f = filters.get(index++);
f.doFilter(request, response, this);
}
}
Tomcat中的责任链模式
简单的上一个链条调用下一个链条
HTTP 协议可简单分为请求头和请求体两部分,Tomcat 在收到一条完整的 HTTP 请求时,也会将其分为请求头和请求体两部分进行处理的。
不过在真正的 Tomcat 实现中,会将 HTTP 请求细分为更多部分,然后逐步进行处理,整个 Tomcat 代码处理 HTTP 请求的实现也更为复杂。
试想一下,Tomcat 将处理请求的各个细节的实现代码都堆到一个类中,那这个类的代码会非常长,维护起来也非常痛苦,可以说是“牵一发而动全身”。如果 HTTP 请求升级,那就需要修改这个臃肿的类,显然是不符合“开放-封闭”原则的。
为了实现像 HTTP 这种多部分构成的协议的处理逻辑,我们可以使用责任链模式来划分协议中各个部分的处理逻辑,将那些臃肿实现类拆分成多个 Handler(或 Interceptor)处理器,在每个 Handler(或 Interceptor)处理器中只专注于 HTTP 协议中一部分数据的处理。我们可以开发多个 Handler 处理器,然后按照业务需求将多个 Handler 对象组合成一个链条,从而实现整个 HTTP 请求的处理。
这样做既可以将复杂、臃肿的逻辑拆分,便于维护,又能将不同的 Handler 处理器分配给不同的程序员开发,提高开发效率。
在责任链模式中,Handler 处理器会持有对下一个 Handler 处理器的引用,也就是说当一个 Handler 处理器完成对关注部分的处理之后,会将请求通过这个引用传递给下一个 Handler 处理器,如此往复,直到整个责任链中全部的 Handler 处理器完成处理。

假设我们自定义了一套协议,其请求中包含 A、B、C 三个核心部分,业务系统使用 Handler A、Handler B、Handler C 三个处理器来处理这三部分的数据。如果业务变化导致我们的自定义协议也发生了变化,协议中的数据变成了 A、C、D 这三部分,那么我们只需要动态调整构成责任链的 Handler 处理器即可,最新的责任链变为 Handler A、Handler C、Handler D。如下图所示:

由此可见,责任链模式可以帮助我们复用 Handler 处理器的实现逻辑,提高系统的可维护性和灵活性,很好地符合了“开放-封闭”原则。
posted on 2025-10-14 23:09 chuchengzhi 阅读(7) 评论(0) 收藏 举报
浙公网安备 33010602011771号