责任链模式,也有的称呼为职责链模式,一个意思。
见名知意:这种模式有两个特点一个是职责,一个是链的形式。
责任是表明了个体的独立性,责任明确,符合单一职责的原则。
链就是个体连接起来,形成一条清晰的线,由点到面,形成职责链,链的形式反映到代码中就是个体的存储方式,比如:链表结构,数组,集合等等,这些存储结构,都是将单独的个体分类,归纳,形成一个群体,这个群体就是责任链,一个个体是不能称为链的,就像不能把一个点称为一条线一样,存储结构在设计模式中有着非常重要的作用。有了存储结构,才能使设计模式得以实现。
这里用学校这个场景举个例子。
我们最常听过的,班长,班主任,年级主任,教导主任,教学副校长,校长。这些应该都不陌生,每个身份都有各自的责任,而且每个职责都是由独立个体担任,很少听说,班长,班主任,年级主任等等都是由个体担任。
这些职级又根据权利大小,职责范围,形成了一条链子。
让这条职责链运转的动力就是事件。等级最小的个体产生了一个事件,本身无法做决定,需要请示具有一定权利的人才行。
比如说:班长的职责就包含维护课堂秩序,以及可以向班主任汇报有关班级的各种信息等。
学生正在上晚自习课,有个学生想上厕所(产生一个事件),学校规定是上课时间不能乱跑(自身无法做决定),所以需要告诉班长,班长是有能力处理这个事件的,就让这个学生去了,这个事件也就处理完毕了,这个事件就结束了。
再举个例子:每次月考完,会有晚自习公布成绩,公布了成绩,就是自习时间。还是有学生提议想用班里的电脑看电影(产生一个事件),就把这个提议告诉了班长,但是班长是没权利让大家使用电脑的,所以就需要把这个事告诉班主任,班主任是可以决定让大家使用电脑看电影的。
再举个例子:有个班里第一名的学生,因为某些原因,要退学。告诉了班长,显而易见,班长是不能大手一挥,做出“同意你退学”这样的决定的。就告诉班主任,班主任也是没权利做决定的,就告诉了年纪主任,依次类推,经过了教导主任,教学副校长,最后传到了校长那里,毕竟只有校长才有权利同意一个学生退学。
从上面的例子就可以进行归纳整理,形成一个抽象概念。班长,班主任,年级主任,教导主任,教学副校长,校长。他们有一个共同的特点,就是管理者。那么用代码来解释,这个管理者就是一个抽象类,他们有一个共同的方法就是处理事件,那么这个处理事件的方法就是一个抽象方法,具体的实现是由具体的责任个体来实现的,班长有班长的处理能力范围,班主任有班主任的处理能力范围。
那么,有没有人会说,开始产生了一个事件,通过这个事件直接找到某个责任人,是不是就不用责任链了。这种想法也没错,不过,可以仔细想想,这种模式是不是跟之前介绍过的【策略模式】一样了,策略模式就是通过自身事件所携带的信息(key),直接在map中找到所对应的处理对象,不是像现在一级一级的传递。
那么这两种模式的不同点就是产生的这个事件,自身有没有携带可以处理事件的相关信息,【策略模式】事件本身就会携带这个信息,就是说,产生的事件可以直接找到相应的处理对象来处理;【责任链模式】是不知道该直接找谁负责,那只能从能接触到的最小职责开始,层层上报,直到找到能负责处理这件事的人(对象,职责负责人)。
- 经典责任链的结构就像每个个体手拉手的样子,每个人都只能与自己相邻的两个人拉手,不能拉了一个人的手再拉下一个人的手,一个人也只有两只手,只能拉两个人,也有人说,能不能跳过某个人,那就说明这个被跳过的人不在这个责任链之内。这个模式可以参考Android View触摸事件传递机制,只要是找到能处理这个触摸事件的View,这个触摸事件就算是结束了。
- 现在的责任链模式也有了许多新的需求和变化,一个事件,不再是跟经典责任链模式一样找到能处理事件的某个责任节点就终止执行了,而是所有的责任链节点都需要过一遍手,都需要在这个事件上做点事,经过所有的责任节点,最终产生了符合要求的结果。这个可以参考Android的网络请求框架Okhttp中的RealCall中*getResponseWithInterceptorChain()*方法,采用的就是这种责任链模式,每个interceptor都是单独的职责个体,都有自己所要负责的职能,如果不考虑出错的情况下,一个正常的请求,不会说到了中间某个责任节点处理完就结束了,而是会一直执行下去,直到最后一个节点,经过每个节点不同的处理,最后产生了我们想要的结果。
@Throws(IOException::class)
internal fun getResponseWithInterceptorChain(): Response {
// Build a full stack of interceptors.
// 使用集合 将每个责任节点 组织起来
val interceptors = mutableListOf<Interceptor>()
interceptors += client.interceptors
interceptors += RetryAndFollowUpInterceptor(client)
interceptors += BridgeInterceptor(client.cookieJar)
interceptors += CacheInterceptor(client.cache)
interceptors += ConnectInterceptor
if (!forWebSocket) {
interceptors += client.networkInterceptors
}
interceptors += CallServerInterceptor(forWebSocket)
val chain = RealInterceptorChain(
call = this,
interceptors = interceptors,
index = 0,
exchange = null,
request = originalRequest,
connectTimeoutMillis = client.connectTimeoutMillis,
readTimeoutMillis = client.readTimeoutMillis,
writeTimeoutMillis = client.writeTimeoutMillis
)
var calledNoMoreExchanges = false
try {
// 驱动责任链开始运行
// 最后得到response 就是我们需要的结果
val response = chain.proceed(originalRequest)
if (isCanceled()) {
response.closeQuietly()
throw IOException("Canceled")
}
return response
} catch (e: IOException) {
calledNoMoreExchanges = true
throw noMoreExchanges(e) as Throwable
} finally {
if (!calledNoMoreExchanges) {
noMoreExchanges(null)
}
}
}
看上面的方法中,val interceptors = mutableListOf<Interceptor>() 是不是很熟悉,一开始我就说过,链的形式反应到代码中就是存储结构,mutableListOf得到的就是一个可变集合ArrayList,通过集合将每个Interceptor组织起来,形成一个群体,这些群体就是一个责任链。
其中运用的特性还是继承,多态,以及存储结构的合理运用。
以上的内容只是个人的理解,可以关注一下我的公众号,有啥好的不好的话,都可以在公众号里面留言,交个朋友。


本文深入解析责任链模式,以学校管理层级和Android OkHttp为例,阐述职责分工、链式传递与策略模式的区别。讨论了如何通过继承、多态和存储结构实现责任链,并介绍了OkHttp中的Interceptor链处理网络请求的过程。
1516

被折叠的 条评论
为什么被折叠?



