美文网首页 移动 前端 Python Android Java
Kotlin(十四)设计模式-行为型模式(责任链模式)

Kotlin(十四)设计模式-行为型模式(责任链模式)

作者: zcwfeng | 来源:发表于2021-01-13 08:19 被阅读0次

用Kotlin偏函数-实现责任链模式

典型的例子是Servlet中Filter和FilterChain接口,做过web开发的应该比较熟悉。

责任链的目的:避免请求的发送者和接受者之间的耦合关系,将这个对象连成一条链,并沿着这个链传递该请求,直到有一个对象处理它为止。

前面opengl的文章,做各种效果美颜等叠加用的就是责任链。

举个例子:
大学学生会管理学生基金,用于各种活动和组织。发生一笔支出时,如果金额100以内,可以由各个分部长审批;超过100,需要会长同意;金额较大超过500需要辅导员同意。此外,有一个限制,超过1000 默认打回申请。

实现一个普通的责任链

data class ApplyEvent(val money: Int, val title: String)
interface ApplyHandler {
    val successor: ApplyHandler?
    fun handleEvent(event: ApplyEvent)
}

class GroupLeader(override val successor: ApplyHandler?) : ApplyHandler {
    override fun handleEvent(event: ApplyEvent) {
        when {
            event.money <= 100 ->
                println("Group leader handle application:${event.title}")
            else -> when (successor) {
                is ApplyHandler -> successor.handleEvent(event)
                else -> println("Group Leader:This application cannot be handle.")
            }
        }
    }
}

class Pressient(override val successor: ApplyHandler?) : ApplyHandler {
    override fun handleEvent(event: ApplyEvent) {
        when {
            event.money <= 500 ->
                println("Group leader handle application:${event.title}")
            else -> when (successor) {
                is ApplyHandler -> successor.handleEvent(event)
                else -> println("Group Leader:This application cannot be handle.")
            }
        }
    }
}

class College(override val successor: ApplyHandler?) : ApplyHandler {
    override fun handleEvent(event: ApplyEvent) {
        when {
            event.money > 1_000 ->
                println("College:This application is refused.")
                else -> println("College handled application :${event.title}")
        }
    }
}

fun main() {
    val college = College(null)
    val president = Pressient(college)
    val groupLeader = GroupLeader(president)
    groupLeader.handleEvent(ApplyEvent(10,"buy a pen"))
    groupLeader.handleEvent(ApplyEvent(200,"team building"))
    groupLeader.handleEvent(ApplyEvent(600,"hold a debate match"))
    groupLeader.handleEvent(ApplyEvent(1200,"annual metting of the college"))
}

每个链条的每个环节都有对它输入参数的校验标准,输入参数在某个责任链环节的有效范围内,该环节做出正常处理,我们还有专业属于描述,就是 “偏函数”

实现偏函数类型:PartialFunction

偏函数:数学概念,定义域X中可能存在某些值,在值域Y中没有对应的值

和普通函数比较 (int) -> Unit ,可以接受任何Int值。在偏函数,指定的参数并不接受任何类型。

// 偏函数
fun mustGreaterThan5(x:Int):Boolean{
    if(x > 5) return true
    else throw Exception("x muster greater than 5")
}

Kotlin 的标准库,并没有支持PartialFunction。然而Scala里面有PartialFunction类型。Ktolin 第三方库(如funKTionale)已经实现了这个功能。

PartialFunction
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 (isDefinetAt(p1)) {
            return f(p1)
        } else {
            throw IllegalArgumentException("Value:$p1 is not support by this function")
        }
    }

    fun isDefinetAt(p1: P1) = definetAt(p1)
}
  • 声明对象的时候接受两个构造参数,其中definetAt 是校验函数,f是处理函数
  • 当PartialFunction类对象执行invoke方法,definetAt会对输出参数p1 进行有效行校验
  • 如果校验结果通过,则执行f函数,同时将p1作为参数传递给它;反过来抛出异常

我们还需要解决一个问题就是,如何在链条请求中进行传递

orElse 扩展,为了可以用中缀表达式,链式调用,添加infix
infix fun <P1, R> PartialFunction<in P1, out R>.orElse(that: PartialFunction<P1, R>): PartialFunction<P1, R> {
    return PartialFunction({ this.isDefinetAt(it) || that.isDefinetAt(it) }) {
        when {
            this.isDefinetAt(it) -> this(it)
            else -> that(it)
        }
    }
}

isDefinetAt 没有特殊的地方就是单纯的拷贝definetAt 方法目的是可以在orElse 中使用
orElse 方法可以传入PartialFunction对象that,也就是责任链后继,如果isDefinetAt 为false 调用that继续申请处理。

orElse 方式实现责任链

利用设计好的PartialFunction类以及扩展orElse方法实现


val groupLeader = {
    val definetAt: (ApplyEvent) -> Boolean = { it.money <= 200 }
    val handler: (ApplyEvent) -> Unit = { println("Group leader handle application:${it.title}") }
    PartialFunction(definetAt, handler)
}()

val president = {
    val definetAt: (ApplyEvent) -> Boolean = { it.money <= 500 }
    val handler: (ApplyEvent) -> Unit = {
        println("Group leader handle application:${it.title}")
    }
    PartialFunction(definetAt, handler)
}()

val college = {
    val definetAt: (ApplyEvent) -> Boolean = { true }
    val handler: (ApplyEvent) -> Unit = {
        when {
            it.money > 1_000 ->
                println("College:This application is refused.")
            else -> println("College handled application :${it.title}")
        }
    }
    PartialFunction(definetAt, handler)
}()
val applyChain = groupLeader orElse president orElse college

fun main() {
    applyChain(ApplyEvent(100,"hold a debate match"))
    applyChain(ApplyEvent(600,"hold a debate match"))
    applyChain(ApplyEvent(1200,"hold a debate match"))

}

val applyChain = groupLeader orElse president orElse college
中缀表达式,kotlin十分灵活。

相关文章

网友评论

    本文标题:Kotlin(十四)设计模式-行为型模式(责任链模式)

    本文链接:https://www.haomeiwen.com/subject/renmoktx.html