责任链模式
定义:
使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系,将这些对象连成一条链,并沿着这条链去传递该请求,直到有对象处理它为止
使用场景
- 多个对象可以处理同一个请求,但具体由那个对象处理则在运行时动态决定
- 在请求处理者不明确的情况下向多个对象中的一个提交一个请求
- 需要动态的指定一组对象处理请求
责任链模式的写法
UML图如下:
- AbstractHandler:抽象处理者角色,声明一个请求处理的方法,并在其中保持一个对下一个处理节点Handler对象的引用
- ConcreateHandler:具体处理者角色,对请求进行处理,如果不能处理则将该请求转发给下一个节点上的处理对象
- AbstractRequest:抽象请求者,其内声明一个获取请求级别的方法,与抽象处理者中返回的处理级别保持对应,什么级别的处理逻辑就对应什么样的请求级别
- ConcreteRequest:具体请求者
设想一个场景:外出公干费用5万,回来之后上报组长报销费用,可是组长只能报销500一下的,然后组长上报部门主管,可是部门主管只能报销5000以下,之后上报老板…..这个过程中“我”只和“组长”有对接,但是具体是谁处理,并不关心,在乎的只是报账的结果,这就是责任链模式的本质,可以很好的将请求的发起者和处理者解耦
定义抽象处理者:抽象领导者
public abstract class Leader {
protected Leader nextHandler; //上一级的领导处理者
public final void handleRequest(int money) {
if (money <= limit()) {
handle(money);
} else {
if (null != nextHandler) {
nextHandler.handleRequest(money);
}
}
}
/**
* 自身能批复的额度权限
* @return 额度
*/
public abstract int limit();
/**
* 处理报账行为
* @param money 具体金额
*/
public abstract void handle(int money);
}
创建具体处理者:具体领导者,组长、主管、经理、老板
//组长
public class GroupLeader extends Leader {
@Override
public int limit() {
return 100;
}
@Override
public void handle(int money) {
System.out.println("组长审批报销"+money+"元");
}
}
//主管
public class DirectorLeader extends Leader {
@Override
public int limit() {
return 5000;
}
@Override
public void handle(int money) {
System.out.println("主管审批报销"+money+"元");
}
}
//经理
public class ManagerLeader extends Leader {
@Override
public int limit() {
return 10000;
}
@Override
public void handle(int money) {
System.out.println("经理审批报销"+money+"元");
}
}
//老板
public class BossLeader extends Leader {
@Override
public int limit() {
return Integer.MAX_VALUE;
}
@Override
public void handle(int money) {
System.out.println("老板审批报销"+money+"元");
}
}
客户端调用:
public class Client {
public static void main(String[] args) {
//构建各个领导对象
GroupLeader groupLeader = new GroupLeader();
DirectorLeader directorLeader = new DirectorLeader();
ManagerLeader managerLeader = new ManagerLeader();
BossLeader bossLeader = new BossLeader();
//设置上一级的领导处理对象
groupLeader.nextHandler = directorLeader;
directorLeader.nextHandler = managerLeader;
managerLeader.nextHandler = bossLeader;
//发起报账申请
groupLeader.handleRequest(50000);
//这里的5000应该是申请人提出的,申请人是具体请求者
}
}
这里请求的发起可以从责任链的任何一个节点处开始,同时也可以改变责任链内部传递的规则,如果主管不在,完全可以跨过主管从组长直接将请求转送给经理
OkHttp拦截器
okhttp中添加各种拦截器以分别处理:详见okhttp整体流程
RealCall#getResponseWithInterceptorChain
Response getResponseWithInterceptorChain() throws IOException {
List<Interceptor> interceptors = new ArrayList<>();
interceptors.addAll(client.interceptors());
interceptors.add(retryAndFollowUpInterceptor);
interceptors.add(new BridgeInterceptor(client.cookieJar()));
interceptors.add(new CacheInterceptor(client.internalCache()));
interceptors.add(new ConnectInterceptor(client));
if (!forWebSocket) {
interceptors.addAll(client.networkInterceptors());
}
interceptors.add(new CallServerInterceptor(forWebSocket));
//将所有的拦截器串成一条chain链
Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
originalRequest, this, eventListener, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
//执行proceed方法获取响应
return chain.proceed(originalRequest);
}
RealInterceptorChain#proceed方法:
public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
RealConnection connection) throws IOException {
if (index >= interceptors.size()) throw new AssertionError();
calls++;
.........
// 判断每一个截获器都有对应的处理,没有则创建RealInterceptorChain,即是创建当前的类,不断的迭代
RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
writeTimeout);
Interceptor interceptor = interceptors.get(index);
//并执行当前的截获器的intercept方法,这个方法其实就是递归调用,若没有形成递归,就是中断了请求
Response response = interceptor.intercept(next);
// Confirm that the next interceptor made its required call to chain.proceed().
if (httpCodec != null && index + 1 < interceptors.size() && next.calls != 1) {
throw new IllegalStateException("network interceptor " + interceptor
+ " must call proceed() exactly once");
}
.........
return response;
}
这里我们可以看到具体处理者就是截获器,详见截获器中的详细介绍