责任链模式主要是用于一个请求有多个处理逻辑的情况,可以减少请求发出者与多个逻辑处理者之间的耦合度。这些处理者通常都是有着相同的输入和输出,但是它们的责任不同。以后端处理一个http请求为例,在到达业务处理前需要判断这个请求是否合法,可能会经历很多层通用的处理,比如请求是否频繁、签名是否正确,是否登录,用户权限是否满足等等,它们的输入都是http请求,输出结果是请求是否合法。
如果不考虑设计模式,对于这个功能,最简单的实现就是写一个通用的方法,然后再封装不同的判断逻辑,一层层判断即可,代码如下
public boolean checkRequest(HttpRequest request) {
return checkFrequentLimit(request) && checkSignature(request) && checkLogin(request) && checkRole(request);
}
责任链模式的核心是把这些处理逻辑串起来形成一条处理链,有很多种实现方式,我个人比较倾向以下这种通过一个控制类把其它所有处理节点串起来的方式。
首先定义对http请求进行过滤的拦截器接口Interceptor及其实现类FrequentInterceptor、SignatureInterceptor、LoginInterceptor。
1public interface Interceptor {
2 boolean intercept(InterceptorChain chain);
3}
4
5public class FrequentInterceptor implements Interceptor {
6 @Override
7 public boolean intercept(InterceptorChain chain) {
8 if (!doIntercept(chain.request)) {
9 return false;
10 }
11 return chain.proceed();
12 }
13
14 private boolean doIntercept(HttpRequest request) {
15 //...
16 }
17}
18
19public class SignatureInterceptor implements Interceptor {
20 @Override
21 public boolean intercept(InterceptorChain chain) {
22 if (!doIntercept(chain.request)) {
23 return false;
24 }
25 return chain.proceed();
26 }
27
28 private boolean doIntercept(HttpRequest request) {
29 //...
30 }
31}
32
33public class LoginInterceptor implements Interceptor {
34 @Override
35 public boolean intercept(InterceptorChain chain) {
36 if (!doIntercept(chain.request)) {
37 return false;
38 }
39 return chain.proceed();
40 }
41
42 private boolean doIntercept(HttpRequest request) {
43 //...
44 }
45}
然后是对外提供的拦截链类InterceptorChain,在proceed方法中依次调用拦截器列表的intercept方法,只要其中一个拦截器返回false,那么整个拦截链则直接返回false,如果执行完了所有的拦截器,则说说明请求合法,返回true。
1public class InterceptorChain {
2
3 public final HttpRequest request;
4 private final List<Interceptor> interceptors;
5 private int index;
6
7 public InterceptorChain(HttpRequest request, List<Interceptor> interceptors) {
8 this.request = request;
9 this.interceptors = interceptors;
10 }
11
12 public boolean proceed() {
13 if (index >= interceptors.size()) {
14 return true;
15 }
16 return interceptors.get(index++).intercept(this);
17 }
18}
在实际项目中可以根据需要对拦截链进行调整,比如说拦截器的优先级,依赖关系等等,看上去比原来直接写还麻烦了很多,但是使用设计模式本身也不是为了减少代码量,而是提高代码的扩展性和可维护性。