概述
责任链模式是一种处理请求的模式,该模式会把多个处理器添加到一个处理器数组(或者通过链表串成一条链),从而使得多个处理器都有机会处理请求。如果当前处理器成功处理请求,会直接返回结果,否则会把当前请求传递给下一个处理器。
当你想要让一个以上的处理器有机会能够处理某个请求的时候,就使用责任链模式。(Chain of Responsibility Pattern) — 引自Head First
- Client:客户端
- Handler:抽象处理者
- ConcreteHandler:具体处理者
使用举例
以员工请假为例子,假设员工小强要请假,制度如下:
- 组长可以审批3天之内的假期(包括3天)
- 部门主管可以审批7天之内的假期(包含7天)
- CEO可以审批任何时间之内的假期
请求Request:
public class Request {
private int num;//请假天数
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
}
处理器Handler:
//声明处理器接口
public interface Handler {
boolean process(Request request);
}
//具体处理器(组长AHandler)
public class AHandler implements Handler {
@Override
public boolean process(Request request) {
if (request.getNum() < 3) {
System.out.println("AHandler(组长)处理了该请假申请");
return true;
}
System.out.println("AHandler(组长)处理不了该申请,往下传递");
return false;
}
}
//具体处理器(部门主管BHandler)
public class BHandler implements Handler {
@Override
public boolean process(Request request) {
if (request.getNum() < 7) {
System.out.println("BHandler(部门主管)处理了该请假申请");
return true;
}
System.out.println("BHandler(部门主管)处理不了该申请,往下传递");
return false;
}
}
//具体处理器(CEO CHandler)
public class CHandler implements Handler {
@Override
public boolean process(Request request) {
System.out.println("CHandler(CEO)处理了该请假申请");
return true;
}
}
处理链Chain:
public class HandlerChain {
private List<Handler> chains = new ArrayList<>();
public void addHandler(Handler handler) {
chains.add(handler);
}
public boolean process(Request request) {
//遍历链中处理器队请求进行处理
for (Handler handler : chains) {
boolean isHandled = handler.process(request);
//如果该处理器成功处理请求,直接返回
if (isHandled) {
return true;
}
}
System.out.println("都处理不了了");
return false;
}
}
如果请假天数为5天:
public static void main(String[] args) {
HandlerChain chain = new HandlerChain();
chain.addHandler(new AHandler());
chain.addHandler(new BHandler());
chain.addHandler(new CHandler());
int requestDay = 5;
Request request = new Request();
request.setNum(requestDay);
System.out.println("请求假期天数为:" + requestDay);
chain.process(request);
}
执行结果:
请求假期天数为:5
AHandler(组长)处理不了该申请,往下传递
BHandler(部门主管)处理了该请假申请
如果将请假天数改为30,即将上述代码中修改为int requestDay = 30;
,从新执行:
请求假期天数为:30
AHandler(组长)处理不了该申请,往下传递
BHandler(部门主管)处理不了该申请,往下传递
CHandler(CEO)处理了该请假申请
责任链模式在Android中的使用
View事件传递
伪代码表示dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent三者之间的关系:
public boolean dispatchTouchEvent (MotionEvent ev){
boolean consume = false;
if (onInterceptTouchEvent(ev)) {
consume = onTouchEvent(ev);
} else {
consume = child.dispatchTouchEvent(ev);
}
return consume;
}
View事件传递也可以认为是一种责任链模式,使得参与的View或者ViewGroup都有机会去处理TouchEvent。
OkHttp
OkHttp中的处理器(拦截器)主要有下面几个:
- 自定义interceptor: 开发者在配置 OkHttpClient时设置;
- RetryAndFollowUpInterceptor: 负责失败重试以及重定向;
- BridgeInterceptor: 负责把用户构造的请求转换为发送到服务器的请求、把服务器返回的响应转换为用户友好的响应;
- CacheInterceptor: 负责读取缓存直接返回、更新缓存;
- ConnectInterceptor: 负责和服务器建立连接;
- networkInterceptors: 配置 OkHttpClient 时设置的;
- CallServerInterceptor: 负责向服务器发送请求数据、从服务器读取响应数据。
OkHttp
中的责任链模式,每个Handler
处理器(拦截器)都有机会去处理Request
,这种处理器更适合称为拦截器(Interceptor),它的目的不是找到某个Handler
处理掉Request
,而是每个Handler
都对Request
做一些工作。
优缺点
优点:
- 将请求的发送者和接受者进行解耦,请求者不需要知道链表的存在
- 通过改变链内的成员或调动它们的次序,允许动态地新增或删除责任。
缺点:
- 并不能保证请求一定会执行,如果没有任何责任链中的对象处理请求的话,请求可能会落到链表的尾端之外(可以新增一个终端处理)。
- 不容易观察运行时的特征,不容易除错。
参考
【1】https://www.liaoxuefeng.com/wiki/1252599548343744/1281319474561057
【2】https://blog.youkuaiyun.com/gdutxiaoxu/article/details/100189121
【3】Android中的责任链模式分析