- 责任链模式
- 定义
- 实现
- 简单实现
- UML类图
- 代码实现
- 筛选请求实现
- UML类图
- 代码实现
- OkHttp责任链的模仿实现
- UML类图
- 代码实现
- 拓展
- 总结
- 参考文献
责任链模式是行为型设计模式之一
行为型模式关注的是对象之间的通信,也就是描述多个类或者对象之间,通过协作共同完成一个任务。主要涉及的是 对象 和 算法之间职责的分配。
行为型模式 可以分为两类:
- 类行为模式: 通过继承机制来在类间分派行为。 主要是通过多态来分配父类和子类的职责
- 对象行为模式: 通过组合或聚合,在对象间分派行为。通过对象关联等方式来分配类的职责。
由于组合方式比继承耦合性低,所以对象行为模式要比类行为模式具有更大的灵活性。所以大部分的行为型设计模式 都是 对象行为模式。
责任链模式则是对象行为模式的一种。
链即链条,链必然会存在节点。类比狗狗的链子,其中的圆环可以拆卸和添加,因此链式结构具有很好的灵活性。而在责任链模式中,每个节点就是一个对象,每个对象拥有不同的处理逻辑,发起请求后,链头先获取请求,再往后遍历,类似链表的遍历,前面的节点有权利选择是否处理,拦截还是继续往下传递。
每个设计模式都有其优缺点,责任链模式的优缺点如下:
优点:
避免了请求的发送者和接收者之间的耦合关系,且不同的请求处理者之间也进行了职责隔离。
缺点:
节点太多可能导致遍历性能下降,如果是递归则更要慎重。
带着上述的优点和缺点,进入实现环节。
简单实现节点之间采用链表的形式存储,每个节点都对处理进行相应。
实现一个对String进行加工的功能.
UML类图节点的共同父类为Handler,子类继承并实现父类的抽象方法handle()
代码实现Handler
abstract class Handler(protected val nextHandler: Handler?) {
abstract fun handle(request: String): String
}
Handler1
class Handler1(handler: Handler?) : Handler(handler) {
override fun handle(request: String): String {
//Handler1自己的处理
val newRequest = "$request -> Handler1处理请求"
return nextHandler?.handle(newRequest) ?: newRequest
}
}
Handler2
class Handler2(handler: Handler?) : Handler(handler) {
override fun handle(request: String): String {
//Handler2自己的处理
val newRequest = "$request -> Handler2处理请求"
return nextHandler?.handle(newRequest) ?: newRequest
}
}
Main
fun main() {
val handler1 = Handler1(Handler2(null))
println(handler1.handle("request"))
}
最终结果为:
request -> Handler1处理请求 -> Handler2处理请求
上述实现是责任链模式最简单的实现,体现出不同的处理者之间的职责隔离,自己处理自己的逻辑,假设说有一个需求,此需求需要先做A操作,再做B操作才能实现,那么就可以使用上述中责任链模式实现,创建两个处理者,分步处理。
筛选请求实现上述的实现中,所有的请求每个节点都需要必须经过,在现实情况中,请求可能需要分类,某些请求可能不需要经过某些处理者,下面实现一个筛选请求的需求。
根据请求码,选择相应处理器进行处理。
UML类图创建Request类,内部包含处理的数据,声明getRequestCode()方法,返回请求码,Handler获取Request的相应码与自己进行对比判断是否需要处理。
代码实现Handler
abstract class Handler(protected var nextHandler: Handler?) {
fun handleRequest(request: Request) {
//若请求码相等则自己处理,否则向下传递
if (getCode() == request.getRequestCode()) {
handle(request)
} else {
nextHandler?.handleRequest(request) ?: println("没有处理者处理此请求")
}
}
//获取Handler的请求码
protected abstract fun getCode(): Int
//具体的处理逻辑
protected abstract fun handle(request: Request)
}
MyHandler1
class MyHandler1(nextHandler: Handler?) : Handler(nextHandler) {
override fun getCode() = 100
override fun handle(request: Request) {
println("${request.getContent()} MyHandler1处理")
}
}
MyHandler2
class MyHandler2(nextHandler: Handler?) : Handler(nextHandler) {
override fun getCode() = 200
override fun handle(request: Request) {
println("${request.getContent()} MyHandler2处理")
}
}
MyHandler3
class MyHandler3(nextHandler: Handler?) : Handler(nextHandler) {
override fun getCode() = 300
override fun handle(request: Request) {
println("${request.getContent()} MyHandler3处理")
}
}
Request
class Request(private val obj: Any, private val code: Int) {
fun getContent() = obj
fun getRequestCode() = code
}
Main
fun main() {
val request1 = Request("first request", 100)
val request2 = Request("second request", 200)
val request3 = Request("third request", 300)
val request4 = Request("fourth request", 400)
//创建责任链 MyHandler1 -> MyHandler2 -> MyHandler3
val handler = MyHandler1(MyHandler2(MyHandler3(null)))
handler.handleRequest(request1)
handler.handleRequest(request2)
handler.handleRequest(request3)
handler.handleRequest(request4)
}
打印结果如下:
first request MyHandler1处理
second request MyHandler2处理
third request MyHandler3处理
没有处理者处理此请求
request4没有处理者处理因此打印没有处理者处理此请求
上述实现是最简单的筛选,直到找到完全相等的Code才会被处理,假设需求改变,责任链上只要Handler code比Request code高或者相等则必须执行该怎么修改呢?
只需修改Handler类中的handleRequest()方法
修改如下:
Handler#handleRequest
fun handleRequest(request: Request) {
//若请求码大于等于则命中
if (getCode() >= request.getRequestCode()) {
handle(request)
}
//无论命中if都往下传递请求
nextHandler?.handleRequest(request) ?: println("后续没有处理者相应了")
}
OkHttp责任链的模仿实现
回想网络请求的过程,客户端发送Request,服务端收到请求后返回Response,客户端再处理此Response,整个过程时一条链的过程,因此使用责任链可以实现。
回想OkHttp的使用:
fun get() {
//创建OkHttpClient
val okHttpClient = OkHttpClient()
val url = "https://www.baidu.com"
val request = Request.Builder()
.url(url)
.build()
val call = okHttpClient.newCall(request)
call.enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
Log.d("get", "onFailure")
}
override fun onResponse(call: Call, response: Response) {
val responseBody = response.body;
if (responseBody != null) {
Log.d("get", responseBody.string())
}
}
})
}
只需要简单的构建一个Request,再调用Call的执行方法即可获取到Response,那HTTP的请求重定向,请求头的封装,底层和Socket的交互是谁做的呢,就是OkHttp中的拦截器。
OkHttp认为从Request到Response需要经历很多步骤,每个步骤都是不同且独立的,因此可以使用责任链模式实现,在OkHttp的责任链上有处理重定向的节点,有处理封装请求头的节点,有负责和底层Socket交互的节点。
下面简单实现OkHttp的责任链模式
UML类图声明链条类,不再使用链表,降低了拦截器之间的耦合,客户端只关注于链条返回的结果,不再关注于具体的处理者,隔离了用户和真正的处理者,在请求发起后从第一个拦截器开始逐步向下执行,最终由最后一个拦截器发出请求,由于是最后一个拦截器发出的请求,因此最后一个拦截器也将最先获取响应,然后将Response逐步返回。
代码实现Interceptor
public interface Interceptor {
String intercept(Chain chain);
}
RetryAndFollowUpInterceptor
public class RetryAndFollowUpInterceptor implements Interceptor {
@Override
public String intercept(Chain chain) {
//可以在执行下一个拦截器之前,做自己的事情
System.out.println("开始执行重试重定向拦截器");
// 执行下一个拦截器
String result = chain.processd(chain.request + "==>经过重试重定向拦截器");
//获得结果后,加一些自己的东西
System.out.println("结束执行重试重定向拦截器");
return result + "==>经过重试重定向拦截器";
}
}
BridgeInterceptor
public class BridgeInterceptor implements Interceptor {
@Override
public String intercept(Chain chain) {
System.out.println("开始执行桥接拦截器");
String result = chain.processd(chain.request + "==>经过桥接拦截器");
System.out.println("结束执行桥接拦截器");
return result + "==>经过桥接拦截器";
}
}
CacheInterceptor
public class CacheInterceptor implements Interceptor {
@Override
public String intercept(Chain chain) {
System.out.println("开始执行缓存拦截器");
String result = chain.processd(chain.request + "==>经过缓存拦截器");
System.out.println("结束执行缓存拦截器");
return result + "==>经过缓存拦截器";
}
}
ConnectInterceptor
public class ConnectInterceptor implements Interceptor {
@Override
public String intercept(Chain chain) {
System.out.println("开始执行连接拦截器");
String result = chain.processd(chain.request + "==>经过连接拦截器");
System.out.println("结束执行连接拦截器");
return result +"==>经过连接拦截器";
}
}
CallServerInterceptor
public class CallServerInterceptor implements Interceptor {
@Override
public String intercept(Chain chain) {
System.out.println("开始执行请求服务器拦截器");
System.out.println("===发起请求===");
System.out.println("结束执行请求服务器拦截器");
return chain.request + "==>经过请求服务器拦截器nHttp响应==>经过请求服务器拦截器";
}
}
Chain
public class Chain {
private List interceptors;
private int index;
public String request;
public Chain(List interceptors, int index, String request) {
this.interceptors = interceptors;
this.index = index;
this.request = request;
}
public Chain(List interceptors, int index) {
this.interceptors = interceptors;
this.index = index;
}
public String processd(String request) {
if (index >= interceptors.size()) {
throw new AssertionError();
}
Chain chain = new Chain(interceptors, index + 1, request);
Interceptor interceptor = interceptors.get(index);
return interceptor.intercept(chain);
}
}
Main
public class Main {
public static void main(String[] args) {
List interceptors = new ArrayList<>();
interceptors.add(new RetryAndFollowUpInterceptor());
interceptors.add(new BridgeInterceptor());
interceptors.add(new CacheInterceptor());
interceptors.add(new ConnectInterceptor());
interceptors.add(new CallServerInterceptor());
//链条对象
Chain chain = new Chain(interceptors, 0);
System.out.println(chain.processd("Http请求"));
}
}
打印结果如下:
拓展开始执行重试重定向拦截器
开始执行桥接拦截器
开始执行缓存拦截器
开始执行连接拦截器
开始执行请求服务器拦截器
=发起请求=
结束执行请求服务器拦截器
结束执行连接拦截器
结束执行缓存拦截器
结束执行桥接拦截器
结束执行重试重定向拦截器
Http请求==>经过重试重定向拦截器==>经过桥接拦截器==>经过缓存拦截器==>经过连接拦截器==>经过请求服务器拦截器
Http响应==>经过请求服务器拦截器==>经过连接拦截器==>经过缓存拦截器==>经过桥接拦截器==>经过重试重定向拦截器
在Android事件分发中也使用了责任链模式,View树等价于责任链,从顶点开始找到可以响应事件的子View,具体的事件分发请看读者的另一篇文章Android事件分发机制详解
总结责任链模式非常灵活,可用的地方很多。
既可以多个对象处理同一请求,也可以一个对象只处理一个请求,主要优点则是避免了请求的发送者和接收者之间的耦合关系,且不同的请求处理者之间也进行了职责隔离。
参考文献何红辉和关爱民老师的《Android 源码设计模式解析与实战》
✨ 原 创 不 易 , 还 希 望 各 位 大 佬 支 持 一 下 textcolor{blue}{原创不易,还希望各位大佬支持一下} 原创不易,还希望各位大佬支持一下
点 赞 , 你 的 认 可 是 我 创 作 的 动 力 ! textcolor{green}{点赞,你的认可是我创作的动力!} 点赞,你的认可是我创作的动力!
⭐️ 收 藏 , 你 的 青 睐 是 我 努 力 的 方 向 ! textcolor{green}{收藏,你的青睐是我努力的方向!} 收藏,你的青睐是我努力的方向!
✏️ 评 论 , 你 的 意 见 是 我 进 步 的 财 富 ! textcolor{green}{评论,你的意见是我进步的财富!} 评论,你的意见是我进步的财富!



