重修设计模式-行为型-责任链模式
将请求的发送和接收解耦,让多个接收对象都有机会处理这个请求。将这些接收对象串成一条链,并沿着这条链传递这个请求,直到链上的某个接收对象能够处理它为止。
责任链模式(Chain of Responsibility Pattern)也叫职责链模式,通过将请求的处理分配给一系列的处理对象,这些处理对象通过链式结构组织起来,以实现对请求的灵活处理。比如,一个请求先经过 A 处理器处理,然后再把请求传递给 B 处理器,B 处理器处理完后再传递给 C 处理器,以此类推,形成一个链条,链条上的每个处理器承担各自的处理职责。
责任链模式的原理非常简单,有两种常用的实现。一种是使用链表来存储处理器,另一种是使用数组来存储处理器,后面一种实现方式更加简单。
1.链表方式
使用链表结构存储处理器,如果有处理器能处理该请求,就不继续往下传递;如果不能处理,则交由后面的处理器来处理。
//处理器
abstract class Handler {
var next: Handler? = null
abstract fun handle()
}
class Handler1: Handler() {
override fun handle() {
var handled = false
//doAction...
handled = Random.nextBoolean()
println("${javaClass.simpleName}处理逻辑... 处理结果:$handled")
//...
if (!handled && next != null) { //如果处理不了,交给下一个处理器
next?.handle()
}
}
}
class Handler2: Handler() {
override fun handle() {
var handled = false
//doAction...
handled = Random.nextBoolean()
println("${javaClass.simpleName}处理逻辑... 处理结果:$handled")
//...
if (!handled && next != null) {
next?.handle()
}
}
}
//处理器链
class HandlerChain {
var head: Handler? = null
var tail: Handler? = null
fun addHandle(handler: Handler) {
handler.next = null
if (head == null) {
head = handler
tail = handler
return
}
tail?.next = handler
tail = handler
}
fun handle() {
head?.handle()
}
}
//使用时:
fun main() {
val chain = HandlerChain()
chain.addHandle(Handler1())
chain.addHandle(Handler2())
chain.handle() //开始责任链调用
}
2.集合方式
使用集合存储所有处理器,调用时通过遍历来串联所有处理器,实现更加简单
//处理器
abstract class HandlerList {
abstract fun handle(): Boolean
}
class HandlerA : HandlerList() {
override fun handle(): Boolean {
var handled = false
//doAction...
handled = Random.nextBoolean()
println("${javaClass.simpleName}处理逻辑... 处理结果:$handled")
//...
//如果处理不了,交给下一个处理器
return handled
}
}
class HandlerB : HandlerList() {
override fun handle(): Boolean {
var handled = false
//doAction...
handled = Random.nextBoolean()
println("${javaClass.simpleName}处理逻辑... 处理结果:$handled")
//...
//如果处理不了,交给下一个处理器
return handled
}
}
//处理器链
class HandlerChainB {
private val chainList = mutableListOf<HandlerList>()
fun addHandle(handler: HandlerList) {
chainList.add(handler)
}
fun handle() {
for (filter in chainList) {
if (!filter.handle()) {
return
}
}
}
}
//调用处:
fun main() {
val chainB = HandlerChainB()
chainB.addHandle(HandlerA())
chainB.addHandle(HandlerB())
chainB.handle()
}
责任链模式可以将请求和处理分开,请求者无需知道处理流程,只关注处理结果;处理者只关注处理逻辑。两者解耦,提高了系统的灵活性和可扩展性。利用它们来提供框架的扩展点,能够让框架的使用者在不修改框架源码的情况下,基于扩展点定制化框架的功能。
传统的责任链定义是,如果处理器链上的某个处理器能够处理这个请求,那就不会继续往下传递请求。实际上,职责链模式还有一种变体,那就是请求会被所有的处理器都处理一遍,不存在中途终止的情况。比如责任链在网络请求的应用:Okhttp
责任链模式在 Okhttp 中的运用
Okhttp 是移动端网络请求的框架,它内部的网络请求实现就用到了责任链模式。具体实现方式是通过集合存储不同职责的拦截器,保证拦截器执行顺序,并通过递归调用的方式将每个拦截器串联起来,从而支持双向拦截:既能拦截客户端发送的请求,也能拦截服务器返回的响应。
getResponseWithInterceptorChain
是 Okhttp 进行网络请求,获取服务端响应结果的核心方法,会通过几个不同职责的拦截器拿到数据,源码如下:
Response getResponseWithInterceptorChain() throws IOException {
//装载不同职责的拦截器
List<Interceptor> interceptors = new ArrayList<>();
interceptors.addAll(client.interceptors()); //1.这是为客户端预留的拦截器扩展,可以拿到纯净的请求
interceptors.add(retryAndFollowUpInterceptor); //2.重试和重定向拦截器
interceptors.add(new BridgeInterceptor(client.cookieJar())); //3.处理请求和响应的Header,如Content-Length
interceptors.add(new CacheInterceptor(client.internalCache())); //4.缓存拦截器,如果有缓存则直接返回缓存数据
interceptors.add(new ConnectInterceptor(client)); //5.构建好TCP链接,确定好编/解码器的拦截器
if (!forWebSocket) {
interceptors.addAll(client.networkInterceptors()); //6.也是为客户端预留的拦截器扩展,可以拿到纯净的响应
}
interceptors.add(new CallServerInterceptor(forWebSocket)); //7.负责访问服务器并拿到响应结果
Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
originalRequest, this, eventListener, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
Response response = chain.proceed(originalRequest); //8.开始拦截器链式调用
if (retryAndFollowUpInterceptor.isCanceled()) {
closeQuietly(response);
throw new IOException("Canceled");
}
return response;
}
拦截器接口定义:
public interface Interceptor {
Response intercept(Chain chain) throws IOException;
interface Chain {
Request request();
Response proceed(Request request) throws IOException;
//...
}
}
具体实现:
public final class RealInterceptorChain implements Interceptor.Chain {
private final List<Interceptor> interceptors;
private final int index;
public RealInterceptorChain(List<Interceptor> interceptors, int index) {
this.interceptors = interceptors;
this.index = index;
}
@Override public Response proceed(Request request) throws IOException {
if (index >= interceptors.size()) throw new AssertionError();
// Call the next interceptor in the chain.
RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
writeTimeout);
Interceptor interceptor = interceptors.get(index);
Response response = interceptor.intercept(next); //自定义拦截器需要调用chain.proceed继续责任链的调用,通过递归方式穿起来了
//...
return response;
}
}
每个拦截器在内部会封装成 RealInterceptorChain
类型,它内部封装了网络的一些通用逻辑,这个可以忽略,内部还是调用了 intercept
方法传递给下一个拦截器,拦截器中又调用 chain.proceed
继续传递,通过递归的方式将拦截器链串联起来,达到双向拦截的效果,例如下面自定义的拦截器:
public final class CustomInterceptor implements Interceptor {
@Override public Response intercept(Chain chain) throws IOException {
//1.对请求进行处理,比如进行gzip压缩
Response networkResponse = chain.proceed(requestBuilder.build());
//2.对响应进行处理,比如gzip解压
return networkResponse;
}
}
总结
责任链模式是一种非常有用的设计模式,它通过链式结构来组织处理者,实现了请求的灵活处理和系统的可扩展性。