责任链模式(Chain of Responsibility Pattern)
一,概念
- 一个请求传过来,有多个处理对象负责对这个请求信息进行处理。这些处理对象处理时组成一条处理链,有先后执行顺序,称为责任链模式。
- 例如你提交的报销单,经过组长,副经理,总经理一层层审批,其中一环审批不通过可以停止审批流程。
- 再举例,一条消息进入某个系统,系统里面有多个过滤文字的处理者。即过滤器或拦截器的作用
- 责任链的好处,在请求和最后的处理中间加了一些中间处理者,请求者不需要知道中间的过滤过程,系统还可以自由的增加减少中间的处理者。
例子1
-
模拟输入的文字信息经过多个过滤对象处理,过滤掉其中不符合规范的html和url信息,如果某个过滤处理的返回值为false,后续的其他处理者不会被执行到。
-
代码
public class Main {
public static void main(String[] args) {
Msg msg = new Msg();
msg.setMsg("大家好:),<script>,欢迎来到 chain.com ,大家都是996 ");
System.out.println("原内容是 :"+msg);
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);
System.out.println("过滤后的内容是 :"+msg);
}
}
class Msg {
String name;
String msg;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
@Override
public String toString() {
return "Msg{" +
"msg='" + msg + '\'' +
'}';
}
}
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;
}
}
class SensitiveFilter implements Filter {
@Override
public boolean doFilter(Msg m) {
String r = m.getMsg();
r = r.replaceAll("996", "955");
m.setMsg(r);
return true;
}
}
class FaceFilter implements Filter {
@Override
public boolean doFilter(Msg m) {
String r = m.getMsg();
r = r.replace(":)", "^V^");
m.setMsg(r);
return true;
}
}
class URLFilter implements Filter {
@Override
public boolean doFilter(Msg m) {
String r = m.getMsg();
r = r.replace("chain.com", "http://www.chain.com");
m.setMsg(r);
return true;
}
}
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) {
if(!f.doFilter(m)) return false;
}
return true;
}
}
`运行结果-----
原内容是 :Msg{msg='大家好:),<script>,欢迎来到 chain.com ,大家都是996 '}
过滤后的内容是 :Msg{msg='大家好^V^,[script],欢迎来到 http://www.chain.com ,大家都是955 '}`
例子2–Servlet过滤器
-
Servlet中的过滤器用到了责任链的模式,它实现的效果是每个过滤者先执行request的过滤,然后执行response的过滤
-
为了让一个过滤器执行前后两次过滤,使用了递归方式
如下模拟Servlet中过滤器的实现。
关键点是执行实际过滤器的doFilter()方法时,多了一个FilterChain 参数,执行过滤的中间调用过滤链的doFilter。
public class Servlet_Main {
public static void main(String[] args) {
Request request = new Request();
request.str = "大家好:),<script>,欢迎访问 chain.com ,大家都是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 f = filters.get(index);
index ++;
f.doFilter(request, response, this);
}
}
执行结果是:
大家好:),[script],欢迎访问 chain.com ,大家都是955 HTMLFilter() SensitiveFilter()
response--SensitiveFilter()--HTMLFilter()
总结
- 如果要求责任链中,处理者可以中断,则可以在执行具体处理动作后加一个布尔返回值,在责任链中进行判断是否继续执行后续处理动作。
- 如果要求责任链中处理者在执行部分操作后,可以对责任链的返回结果进行处理,需要在执行实际过滤器的doFilter()方法时,加一个FilterChain 参数