职责链模式的思想
将事情或许数据传递到第一个处理者身上,每一个处理者都持有下一个处理者的引用,从第一个处理者开端决议:
-
阻拦数据自己处理,不传递给后边的处理者
-
不阻拦数据,加工数据后传递给下一个处理者
-
。。。重复步骤1,2
-
假如都没人阻拦,数据一向回来到最初的地方(经过return的办法,后边经过比如演示)
比如
建议把代码复制到编辑器里点击跳转走一遍,更容易了解
像okhttp那样,经过制作者模式增加所写的阻拦器
fun main() {
val data = "hello"
val jkHttpClient = JkHttpClient.Builder()
.baseUrl(data)
.addInterceptor(LoggerInterceptor())//增加阻拦器的先后顺序会影响成果
.addInterceptor(EncodeInterceptor())
.build()
jkHttpClient.enqueue {
println("用户收到的json数据: ${it}")
}
}
class JkHttpClient(
private val url: String,
private val interceptorList: MutableList<Interceptor>
) {
class Builder {
private var interceptorList = mutableListOf<Interceptor>()
private var url = ""
fun baseUrl(url: String): Builder {
this.url = url
return this
}
fun addInterceptor(interceptor: Interceptor): Builder {
interceptorList.add(interceptor)
return this
}
fun build(): JkHttpClient {
return JkHttpClient(url, interceptorList)
}
}
fun enqueue(callback: (String) -> Unit) {
val realChainProcessor = RealChainProcessor(0, interceptorList)
//当时第二个参数传的null没任何含义
val response = realChainProcessor.proceed(url, null)
callback.invoke(response)
}
}
这里经过enqueue办法去建议恳求,详细的操作交给了RealChainProcessor的proceed办法,并将终究成果回调出去
界说所需要的功能接口
interface Interceptor {
//完成类做处理的办法
fun intercept(url: String, chain: Chain): String
interface Chain {
//建议恳求
fun request(url: String, chain: Chain): String
//阻拦器处理数据
fun proceed(url: String, chain: Chain?): String
//回来成果
fun response(url: String): String
}
}
这里界说接口办法的时候,因为不是彻底按照okhttp的写法,只是大约模仿个进程,一会儿想不到办法配什么参数,是否要回来值,回来值是什么,都是编写边想边改的
class RealChainProcessor(var index: Int, val interceptorList: MutableList<Interceptor>) : Interceptor.Chain {
override fun request(url: String, chain: Interceptor.Chain): String {
//建议网络恳求
println("伪装建议网络恳求")
return chain.response(url)
}
override fun proceed(url: String, chain: Interceptor.Chain?): String {
//当index大于等于阻拦器的数量的时候,阐明阻拦器都现已履行完了,这时候需要去建议网络恳求了
if (index >= interceptorList.size) {
return chain!!.request(url, chain)
} else {
val interceptor = interceptorList[index]
//拿到下一个阻拦器的处理目标
val nextProcessor = RealChainProcessor(index + 1, interceptorList)
//遍历阻拦器
index ++
//当时的阻拦器去履行详细的处理操作,并将下一个处理目标提早传入,
//当处理操作完毕后,经过处理目标可以进行自己的处理操作
return interceptor.intercept(url, nextProcessor)
}
}
override fun response(url: String): String {
//模仿收到网络恳求数据
val data = "{"id":"123456" , "name":"小明"}"
return data
}
}
class LoggerInterceptor() : Interceptor {
override fun intercept(url: String, chain: Interceptor.Chain): String {
println("打印恳求前数据: ${url}")
//等建议网络恳求后打印回来的网络上数据
//因为咱们还有一个阻拦器没有处理,这里拿到的chain为EncodeInterceptor所对应的处理者realChainProcessor
//再接着就是履行processd办法
val response = chain.proceed(url, chain)
//等一切都履行完,数据都return 履行打印并回来到上一层
println("打印恳求后数据: ${response}")
return response
}
}
class EncodeInterceptor : Interceptor {
override fun intercept(url: String, chain: Interceptor.Chain): String {
val newUrl = EncodeUtils.encode(url)
println("数据加密后发给服务器: ${newUrl}")
val response = chain.proceed(newUrl, chain)
//等一切都履行完,数据都return 履行打印并回来到上一层
println("数据解密回来给客户端")
val newResponse = EncodeUtils.decode(response)
return newResponse
}
}
//没含义加解密
object EncodeUtils {
fun encode(url: String): String {
return "${url}abcabc"
}
fun decode(url: String): String {
return "数据已解密 $url"
}
}
总结
大致的框架就出来了,从装备参数,到详细处理者的派发事情,各类各司其责,阻拦器插拔便利,okhttp代码设计的的确好。
我上面的注释可能写的不是很明晰,强烈建议对着okhttp源码自己探索一遍,或许把以上代码复制到编辑器里点击跳转走一遍。
之后各位同学想练习的话也可以模仿view的事情分发机制写个简单的进程,我这边就不展示了,也不是很难。