責任鏈模式是一種對象的行爲模式。經過創建一條鏈來組織請求的處理者,請求將沿着鏈進行傳遞,請求發送者無須知道請求在什麼時候、何處以及如何被處理,實現了請求發送者與處理者的解耦。html
如Android 中的事件傳遞,Activity->ViewGroup->View,固然也能夠View->ViewGroup-> Activity ,android 中是U形事件傳遞android
另外OKhttp的interceptors實現,OkHttp發送網絡請求的一切核心功能,包括創建鏈接、發送請求、讀取緩存等,都是經過interceptors來實現的。這些interceptors在運行的時候彼此協做,構成了一個責任鏈interceptor chain
git
Response getResponseWithInterceptorChain() throws IOException { // Build a full stack of interceptors. List<Interceptor> interceptors = new ArrayList<>(); interceptors.addAll(client.interceptors()); interceptors.add(retryAndFollowUpInterceptor); interceptors.add(new BridgeInterceptor(client.cookieJar())); interceptors.add(new CacheInterceptor(client.internalCache())); interceptors.add(new ConnectInterceptor(client)); if (!forWebSocket) { interceptors.addAll(client.networkInterceptors()); } interceptors.add(new CallServerInterceptor(forWebSocket)); Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0, originalRequest, this, eventListener, client.connectTimeoutMillis(), client.readTimeoutMillis(), client.writeTimeoutMillis()); return chain.proceed(originalRequest); } 複製代碼
在 OkHttp 中,命令對象就是 Request 對象,處理對象就是每個 Interceptor 對象。每一個 interceptor 對 request 進行一些步驟的處理,而將其他的工做交給下一個 interceptor。注意到,責任鏈中的處理對象若是能夠全權處理命令對象,則不須要交給下一個處理對象。OkHttp 中的 CacheInterceptor 也是具備全權處理的能力。若是請求的結果已經緩存,則不須要再交給 ConnectInterceptor 等進行鏈接服務器、發送請求的處理,直接返回已緩存的 response 便可。github
例如常見的流程審批(固然在企業級APP中由服務端處理)編程
fun main(args: Array<String>) { // 引用鏈 val cto = CTO(null) val department = DepartmentLeader(cto) val group = GroupLeader(department) // group.handleEvent(FlowEvent("filepath ", 113)) } data class FlowEvent(val filePath: String, val fileID: Int) interface FlowHandler { val next: FlowHandler? fun handleEvent(event: FlowEvent) } class GroupLeader(override val next: FlowHandler?) : FlowHandler { override fun handleEvent(event: FlowEvent) { when (event.fileID) { // 根據文件ID分配審批權限 處理 111 -> print("GroupLeader收到流程:${event.filePath}") // 不然轉發 else -> when (next) { // 轉發到下一級 is FlowHandler -> { println("GroupLeader: 此流程被轉發了") next.handleEvent(event) } else -> println("GroupLeader: 此流程不能被處理") } } } } class DepartmentLeader(override val next: FlowHandler?) : FlowHandler { override fun handleEvent(event: FlowEvent) { when (event.fileID) { // 根據文件ID分配審批權限 處理 112 -> println("DepartmentLeader收到流程:${event.filePath}") // 不然轉發 else -> when (next) { // 轉發到下一級 is FlowHandler -> { println("DepartmentLeader: 此流程被轉發了") next.handleEvent(event) } else -> println("DepartmentLeader: 此流程不能被處理") } } } } class CTO(override val next: FlowHandler?) : FlowHandler { override fun handleEvent(event: FlowEvent) { when (event.fileID) { // 根據文件ID分配審批權限 113 -> println("CTO收到流程 :${event.filePath},正在處理") else -> println("CTO: 此流程不能被處理") } } } 複製代碼
輸出:api
GroupLeader: 此流程被轉發了
DepartmentLeader: 此流程被轉發了
CTO收到流程文件:filepath
複製代碼
以上能夠參見責任鏈的工做機理,整個鏈條的每一個處理環節都有 對其輸入參數的校驗,只有輸入參數在責任鏈環節的有效接收範圍以內,才能處理相關的邏輯緩存
偏函數是數學中的概念,指的是定義域X中可能存在某些值在值域Y中沒有相對應的值。bash
一個多元函數傳入了部分參數以後的獲得的新的函數。 參數的固定通常使用默認參數+具名參數。若是須要固定的參數在中間,雖說能夠經過具名參數來解決,可是很尷尬,由於必須使用一大堆具名參數。g服務器
Function參見這裏markdown
fun main(args: Array<String>) { val chain = GroupLeader orElse DepartmentLeader orElse CTO chain(FlowEvent("xxxxx",113)) } /** * 責任鏈模式中各環節對於輸入的校驗已經處理邏輯的問題。 * * 協變- 泛型對象做爲函數的參數,逆變- 泛型做爲內部方法的返回。 * * @param check 校驗函數 * @param handle 處理函數 */ class ChainFunction<in P1, out R>( private val check: (P1) -> Boolean, private val handle: (P1) -> R) : (P1) -> R { // 進行有效性檢驗 傳遞參數p1 override fun invoke(p1: P1): R { if (check(p1)) { // 校驗經過執行handle函數 return handle(p1) } else { // 檢驗不經過拋出異常 throw IllegalArgumentException("事件: ($p1) 沒法被處理 ") } } fun isChecked(p1: P1) = check(p1) } // 利用中綴函數造成引用鏈 infix fun <P1, R> ChainFunction<P1, R>.orElse(function: ChainFunction<P1, R>): ChainFunction<P1, R> { return ChainFunction({ this.isChecked(it) || function.isChecked(it) }) { when { this.isChecked(it) -> this(it) else -> function(it) } } } val GroupLeader = { val event: (FlowEvent) -> Boolean = { it.fileID == 111 } val handler: (FlowEvent) -> Unit = { print("GroupLeader已處理該流程:filePath ${it.filePath}") } // 傳遞 ChainFunction(event,handler) }() val DepartmentLeader = { val event: (FlowEvent) -> Boolean = { it.fileID == 112 } val handler: (FlowEvent) -> Unit = { print("DepartmentLeader已處理該流程:filePath ${it.filePath}") } // 傳遞 ChainFunction(event,handler) }() val CTO = { val event: (FlowEvent) -> Boolean = { it.fileID == 113 } val handler: (FlowEvent) -> Unit = { print("CTO已處理該流程:filePath ${it.filePath}") } // 傳遞 ChainFunction(event,handler) }() 複製代碼
CTO已處理該流程:filePath xxxxx
複製代碼
若是責任鏈過長,或者鏈上的事件傳遞須要判斷處理時間太長的話會影響性能,尤爲是遞歸循環。
參考:
funKTionale 《Kotlin核心編程》