职责链模式的思想

事情或许数据传递到第一个处理者身上,每一个处理者都持有下一个处理者的引用,从第一个处理者开端决议:

  1. 阻拦数据自己处理,不传递给后边的处理者

  2. 不阻拦数据,加工数据后传递给下一个处理者

  3. 。。。重复步骤1,2

  4. 假如都没人阻拦,数据一向回来到最初的地方(经过return的办法,后边经过比如演示)

通过okhttp拦截器demo加深对责任链模式的理解

比如

建议把代码复制到编辑器里点击跳转走一遍,更容易了解

像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的事情分发机制写个简单的进程,我这边就不展示了,也不是很难。