责任链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
每一个对象只会处理自己范围内的事情,过界就交给其他对象继续执行,整个过程逻辑上就形成了一个链。
给出一个场景:当向数据库存储一条数据的时候Msg,对于Msg可能会有一些违规的信息,敏感词之类的,这个时候就要在实际存储到数据库前进行一些操作;常规的想法就是加一些过滤器 (学习Java最熟悉的应该就是Filter)
就这个样子
- 最常规的写法
public class Main {
public static void main(String[] args) {
Msg msg = new Msg();
msg.setMsg("大家好:<a href='xxx.com'> 我是xxx </a>, 限时998!(狗头");
// 1.如何替换 <a> 代码,替换敏感词 998 和 狗头表情
String message = msg.getMsg();
message = message.replace('<', '[');
message = message.replace('>', ']');
message = message.replace("998", "998元");
message = message.replace("狗头", "禁止狗头保命");
msg.setMsg(message);
System.out.println(msg);
}
}
class Msg {
private String msg;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
@Override
public String toString() {
return "Msg{" +
"msg='" + msg + '\'' +
'}';
}
}
类似的,可以将不同的处理逻辑单独进行封装:
class HTMLFilter implements Filter {
@Override
public Filter doFilter(Msg msg) {
String message = msg.getMsg();
msg.setMsg(message.replace('<', '[').replace('>', ']'));
return this;
}
}
class SensitiveFilter implements Filter {
@Override
public Filter doFilter(Msg msg) {
msg.setMsg(msg.getMsg().replace("998", "998元"));
return this;
}
}
class DogFaceFilter implements Filter {
@Override
public Filter doFilter(Msg msg) {
msg.setMsg(msg.getMsg().replace("狗头", "禁止狗头保命"));
return this;
}
}
简单的写法就是全写在主程序中,很明显代码耦合太强,不易扩展;如果处理逻辑复杂,代码会很复杂,如果有其他过滤条件,需要更改源程序。
解决方案:由一个对象统一处理,作为统一入口 -》 可以考虑集合
public static void main(String[] args) {
Msg msg = new Msg();
msg.setMsg("大家好:<a href='xxx.com'> 我是xxx </a>, 限时998!(狗头");
// 统一管理过滤器
List<Filter> chains = new ArrayList<>();
chains.add(new HTMLFilter());
chains.add(new SensitiveFilter());
chains.add(new DogFaceFilter());
for (Filter filter : chains) {
filter.doFilter(msg);
}
System.out.println(msg);
}
将所有需要的过滤器统一保存,然后顺次执行。
- FilterChain
进一步的,如何将集合中的Filter构造成链? 虽说是链,也只是一种逻辑概念,一种顺次执行吧(自己理解)
class FilterChain {
List<Filter> chains = new ArrayList<>();
public FilterChain add(Filter filter) {
chains.add(filter);
return this; // 链式编程
}
public void doFilter(Msg msg) {
for (Filter filter : chains) {
filter.doFilter(msg);
}
}
}
这里的 return this 是一种编程写法,这样可以在调用的时候链式编程
chain.add(new HTMLFilter()).add(new DogFaceFilter());
JavaWeb中Servlet对于Filter的实现,如果处理Request和Response,并保证Request和Response的处理是相反的?
在JavaEE中的实现是传入第三个参数FilterChain,然后利用递归的思想进行调用
1. 自定义Request, Response
class Request {
String str;
}
class Response {
String str;
}
2. 赋予过滤器可以终止行为的功能,如果不满足添加可以直接return false,进行终止;并且整体过滤器的进行不在用for进行统一执行,而用Index控制
class HTMLFilter implements Filter {
@Override
public Filter doFilter(Request request, Response response, FilterChain chain) {
request.str += "1";
chain.doFilter(request, response);
response.str += "1";
return this;
}
}
这里HTMLFilter中执行的是 += “1”, 其他的依次 += “2”, += “3”就行了,就是为了显示效果。
3. 定义过滤器链
class FilterChain {
List<Filter> chains = new ArrayList<>();
int index = 0;
public FilterChain add(Filter filter) {
chains.add(filter);
return this;
}
public void doFilter(Request request, Response response) {
if (index == chains.size()) return;
Filter filter = chains.get(index); // 获取当前Filter
index ++;
filter.doFilter(request, response, this); // 具体Filter的执行逻辑
}
}
4. 主程序调用
public static void main(String[] args) {
FilterChain chain = new FilterChain();
chain.add(new HTMLFilter()).add(new SensitiveFilter()).add(new DogFaceFilter());
Request request = new Request(); request.str = "request:";
Response response = new Response(); response.str = "response:";
chain.doFilter(request, response);
System.out.println(request.str + " " + response.str);
}
5.运行结果