1.责任链模式的定义(百度百科)
责任链模式是一种设计模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。
从上面,我们可以了解到,责任链模式的关键之处在于存在一个链条,每个链条上都存在一个业务处理的对象,每个请求到达时,可以按照链条上的顺序依次处理。我们web中常用的filter,就是这种采用模式实现,将多个配置的filter串成一个链条,按照顺序依次处理。
2.案例
假如我们现在有一个业务需求,对一段文字进行XSS脚本、敏感词处理。我们可以使用以下代码简单实现。
public class Test {
public static void main(String[] args) {
String str = "120,<alert>hello word</alert>";
// XSS
str = str.replace("<", "[").replace(">", "]");
// 敏感词
str = str.replace("120", "hello");
System.out.println(str);
}
}
这种方式处理最简单,直接在一个方法中进行处理,但是当XSS、敏感词规则变多,或者需要增加新的规则时,就需要修改原来的逻辑,并且代码会越来越难以维护。
3.责任链模式的实现
3.1 对业务进行抽象
无论是XSS处理、还是敏感词处理,都需要对这个字符串的内容进行过滤,我们可以把这个业务抽象出来。
public interface MessageHandler {
boolean doHandler(Message message);
}
然后就有2个对应的实现类。
public class XssHandler implements MessageHandler {
@Override
public boolean doHandler(Message message) {
String msg = message.getMessage();
msg = msg.replace("<", "[").replace(">", "]");
message.setMessage(msg);
return true;
}
}
public class SensitiverHandler implements MessageHandler {
@Override
public boolean doHandler(Message message) {
String msg = message.getMessage();
msg = msg.replace("120", "hello");
message.setMessage(msg);
return true;
}
}
3.2 设置责任链
通过上一步,我们把每种处理方式分离开了,现在要做的就是把每种方式串起来,形成一个链条。在这个链条中,对外提供出添加、修改、执行Handler的方法,这个客户端就可以操作这个链条了。
我们也可以在doHandler执行方法中,根据业务的返回结果,将链条中断,不继续向下执行。
public class HandlerChain {
private List<MessageHandler> handlers = new ArrayList<>();
public HandlerChain addHandler(MessageHandler handler) {
handlers.add(handler);
return this;
}
public HandlerChain remove(MessageHandler handler) {
handlers.remove(handler);
return this;
}
public boolean doHandler(Message message) {
for (MessageHandler handler : handlers) {
boolean bool = handler.doHandler(message);
if (!bool) {
return false;
}
}
return true;
}
}
为了方便操作这个链条,可以用简单工厂对外提供一个链条。
public class HandlerChainFactory {
public static HandlerChain getHandlerChain() {
HandlerChain handlerChain = new HandlerChain();
handlerChain.addHandler(new XssHandler())
.addHandler(new SensitiverHandler());
return handlerChain;
}
}
3.3 客户端使用责任链
通过HandlerChainFactory获取到责任链条,然后调用doHandler方法,就可以进行XSS、敏感词处理了。当需要新增规则时,只需要实现MessageHandler,并将其加入到链条中,就可以实现了。
/**
* 责任链模式
*/
public class Client {
public static void main(String[] args) {
Message message = new Message();
message.setMessage("120,<alert>hello word</alert>");
HandlerChain handlerChain = HandlerChainFactory.getHandlerChain();
handlerChain.doHandler(message);
System.out.println(message.toString());
}
}