重学设计模式之责任链设计模式(Kotlin)

500 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第九天,点击查看活动详情 

前言

责任链模式(Chain of Responsibility Pattern)是一种处理请求的模式,他能让多个处理器都有机会处理该请求,直到其中某个处理成功为止。使用的场景很多,在Android中最常见的地方就是点击事件的传递

使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止

使用场景

  1. 多个对象可以处理同一个请求,但具体由哪个对象处理则在运行时动态决定

建造者模式角色以及职责

  1. 在请求处理者不明确的情况下向对个对象中的一个提交一个请求

  2. 需要动态处理一组对象处理请求

责任链模式角色以及职责

  • 抽象处理者(Handler):定义一个处理请求的接口,包含抽象处理方法和一个后继连接

  • 具体处理者(Concrete Handler):实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者

  • 客户类(Client):创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程

1.png

实例

我们以程序员涨工资为例,实战一下责任链模式

  1. 我们创建一个涨薪请求类RaiseRequest:
class RaiseRequest(
    //涨薪姓名
    val name: String,
    //涨薪金额
    val num: Int,
    //涨薪缘由
    val content: String
) {
}
  1. 创建一个抽象处理类Handler
abstract class Handler(
    //设置能处理薪资范围
    val numStart: Int, val numEnd: Int
) {

    //领导上还有领导
    private var nextHandler: Handler? = null


    //设置上级领导
    fun setNextHandler(nextHandler: Handler?) {
        this.nextHandler = nextHandler
    }

    //提交涨薪
    fun submit(raiseRequest: RaiseRequest) {
        if (numStart == 0) {
            return
        }

        //涨薪范围达到领导处理要求
        if (raiseRequest.num in numStart..numEnd) {
            handleRaise(raiseRequest)
        }else{
            handNoRights(raiseRequest)
        }

        //如果还有上级 并且涨薪范围超过当前领导的处理范围
        if (nextHandler != null && raiseRequest.num > numEnd) {
            //继续提交
            nextHandler!!.submit(raiseRequest)
        } else {
            println("流程结束!!!")
        }
    }

    //各级领导处理涨薪方法
    protected abstract fun handleRaise(raiseRequest: RaiseRequest)

    //处理不了向上级汇报
    protected abstract fun handNoRights(raiseRequest: RaiseRequest)


    companion object {
        const val NUM_ONE = 300
        const val NUM_THREE = 500
        const val NUM_SEVEN = 1000
    }
}
  1. 我们在来创建具体处理者,GroupLeaderManagerGeneralManager:

GroupLeader:

//小组组长
class GroupLeader
    : Handler(NUM_ONE, NUM_THREE) {

    override fun handleRaise(raiseRequest: RaiseRequest) {
        println(
            raiseRequest.name + "要求涨薪" + raiseRequest.num + "元,涨薪原因:" + raiseRequest.content + "!"
        )

        println("小组长审批通过:同意!")
    }

    override fun handNoRights(leave: RaiseRequest) {
        println("涨薪太大小组长没得权利处理。。。")
    }
}

Manager

//部门经理
class Manager
    : Handler(NUM_THREE, NUM_SEVEN) {

    override fun handleRaise(raiseRequest: RaiseRequest) {
        println(
            raiseRequest.name + "要求涨薪" + raiseRequest.num + "元,涨薪原因:" + raiseRequest.content + "!"
        )
        println("部门经理审批通过:同意!")
    }

    override fun handNoRights(raiseRequest: RaiseRequest) {
        println("涨薪太大部门经理没得权利处理。。。")
    }
}

GeneralManager

//总经理类
class GeneralManager
    : Handler(NUM_SEVEN, Int.MAX_VALUE) {

    override fun handleRaise(raiseRequest: RaiseRequest) {
        println(
            raiseRequest.name + "要求涨薪" + raiseRequest.num + "元,涨薪原因:" + raiseRequest.content + "!"
        )
        println("总经理审批通过:同意!")
    }

    override fun handNoRights(raiseRequest: RaiseRequest) {
        println("我能处理,但我不同意,哈哈")
    }
}
3. 我们再来创建**客户类**`Client`

object Client { @JvmStatic fun main(args: Array) { //请假条 val raiseRequest = RaiseRequest("小菜", 3000, "人长得帅")

    //各位领导
    val manager = Manager()
    val groupLeader = GroupLeader()
    val generalManager = GeneralManager()

    //小组长上司是经理 经理上司是总经理
    groupLeader.setNextHandler(manager)
    manager.setNextHandler(generalManager)

    //提交
    groupLeader.submit(raiseRequest)
}

}

输出结果:

涨薪太大小组长没得权利处理。。。
涨薪太大部门经理没得权利处理。。。
小菜要求涨薪3000元,涨薪原因:人长得帅!
总经理审批通过:同意!
流程结束!!!

责任链设计模式的优缺点

优点:

  • 降低了对象之间的耦合度。该模式使得一个对象无须知道到底是哪一个对象处理其请求以及链的结构,发送者和接收者也无须拥有对方的明确信息

  • 增强了系统的可扩展性。可以根据需要增加新的请求处理类,满足开闭原则

  • 增强了给对象指派职责的灵活性。当工作流程发生变化,可以动态地改变链内的成员或者调动它们的次序,也可动态地新增或者删除责任

  • 责任分担。每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则

缺点:

  • 不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理

  • 对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响

  • 可能不容易观察运行时的特征,有碍于除错