• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

Kotlin~责任链模式

武飞扬头像
不会画板子的物联网工程师
帮助1

概念

允许多个对象按顺序处理请求或任务。

角色介绍

  • Handler: 处理器接口,提供设置后继者(可选)
  • ConcreteHandler:具体处理器,处理请求

UML

学新通

代码实现

学新通

比如ATM机吐钱就可以使用责任链实现。

class PartialFunction<in P1, out R>(
    private val definetAt: (P1) -> Boolean,
    private val f: (P1) -> R
) : (P1) -> R {
    override fun invoke(p1: P1): R {
        if (definetAt(p1)) {
            return f(p1)
        } else {
            throw IllegalAccessException()
        }
    }

    fun isDefinedAt(p1: P1) = definetAt(p1)
}

/**
 * orElse 方法种可以传入另一个 PartialFunction 类对象 that,它也就是责任链模式中的后继者
 * infix 关键字让 orElse 成为一个中缀函数,从而让责任链调用的语法变得更加直观
 */
infix fun <P1, R> PartialFunction<P1, R>.orElse(that: PartialFunction<P1, R>): PartialFunction<P1, R> {
    return PartialFunction({
        this.isDefinedAt(it) || that.isDefinedAt(it)
    }) {
        when {
            this.isDefinedAt(it) -> this(it)
            else -> that(it)
        }
    }
}

什么是偏函数?

在Scala中偏函数使用PartialFuncation构建只处理输入参数的部分分支的函数,也就是带判断条件的函数。在python中作用就是把一个函数的某些参数给固定住(也就是设置成默认值),返回一个新的函数。这样调用的时候就会比较简单。

data class Current(var cash: Int, val message: MutableList<String>)

val RMB_5 = run {
    val definetAt: (Current) -> Boolean = { it.cash >= 5 }
    val handler: (Current) -> Unit = {
        println("处理5元")
        val num = it.cash / 5
        it.cash = it.cash % 5
        it.message.add("5元 * $num")
    }
    PartialFunction(definetAt, handler)
}
val RMB_10 = run {
    val definetAt: (Current) -> Boolean = { it.cash >= 10 }
    val handler: (Current) -> Unit = {
        println("处理10元")
        val num = it.cash / 10
        it.cash = it.cash % 10
        it.message.add("10元 * $num")
    }
    PartialFunction(definetAt, handler)
}
val RMB_20 = run {
    val definetAt: (Current) -> Boolean = { it.cash >= 20 }
    val handler: (Current) -> Unit = {
        println("处理20元")
        val num = it.cash / 20
        it.cash = it.cash % 20
        it.message.add("20元 * $num")
    }
    PartialFunction(definetAt, handler)
}
val RMB_50 = run {
    val definetAt: (Current) -> Boolean = { it.cash >= 50 }
    val handler: (Current) -> Unit = {
        println("处理50元")
        val num = it.cash / 50
        it.cash = it.cash % 50
        it.message.add("50元 * $num")
    }
    PartialFunction(definetAt, handler)
}
val RMB_100 = run {
    val definetAt: (Current) -> Boolean = { it.cash >= 100 }
    val handler: (Current) -> Unit = {
        println("处理100元")
        val num = it.cash / 100
        it.cash = it.cash % 100
        it.message.add("100元 * $num")
    }
    PartialFunction(definetAt, handler)
}

fun ATMMachine(atmChain: PartialFunction<Current, Unit>, cash: Current): Int {
    atmChain(cash)
    return if (cash.cash < 5) {
        if (cash.cash > 0) {
            cash.message.add("1元 * ${cash.cash}")
        }
        0
    } else {
        ATMMachine(atmChain, cash)
    }
}

fun main(args: Array<String>) {
    val atmChain = RMB_100 orElse RMB_50 orElse RMB_20 orElse RMB_10 orElse RMB_5
    val user = Current(1084, ArrayList<String>())
    ATMMachine(atmChain, user)
    for (s in user.message) {
        println(s)
    }
}

优缺点

优点

  • 分离发送着和接收者
  • 链中的灵活性
  • 易于扩展和维护

缺点

  • 无法保证处理请求
  • 性能开销较大
  • 调试复杂度高

应用场景

有多个对象可以处理请求,动态添加、删除修改请求处理器。

  • 中间件
  • GUI时间处理器
  • 异常处理
  • 工作流

总结

责任链平时在业务开发中使用较少,像OkHttp网络请求框架就使用了责任链模式。它里面定义了主要以下几个拦截器:

  • RetryAndFollowUpInterceptor : 负责失败重试和重定向

  • BridgeIntezceptor : 负责处理http 通用请求头和返回头,Cookie

  • CacheInterceptor : 负责处理缓存

  • ConnectInterceptor : 开启和服务器的连接

  • networkInterceptors : 用户定义的网络拦截器,权限更高,更接近底层,一般不需要关注

  • CallServerInterceptor : 实现网络请求

具体可以参考OKHTTP源码解析

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhfckhjg
系列文章
更多 icon
同类精品
更多 icon
继续加载