重学设计模式之命令模式(Kotlin)

289 阅读4分钟

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

重学设计模式之命令模式(Kotlin)

前言

命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。这样使得请求发送者与接受者消除彼此之间的耦合,让对象之间的调用关系更加灵活

命令模式可以对发送者和接收者完全解耦,发送者与接收者之间没有直接引用关系,发送请求的对象只需要知道如何发送请求,而不必知道如何完成请求。这就是命令模式的模式动机

适用场景

  1. 系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互

  2. 在需要支持撤销和恢复撤销的地方,如GUI、文本编辑器等

  3. 需要用到日志请求、队列请求的地方

命令模式的角色以及职责

  1. 抽象命令类(Command): 定义命令的接口,声明执行的方法

  2. 具体命令(Concrete Command):具体的命令,实现命令接口;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。

  3. 实现者/接收者(Receiver) : 接收者,真正执行命令的对象。任何类都可能成为一个接收者,只要它能够实现命令要求实现的相应功能。

  4. 调用者/请求者(Invoker) : 要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口

1162500-20181205110855978-81103218.png

实例

我们就以我们程序员的日常中,客户把开发订单给到老板,但是老板又不会开发,就命令我们根据订单来开发,呜呜呜,想想都为打工仔悲哀,出最大力那最少钱😭,我们就以这个悲惨的现象为例,实现命令模式:

  1. 创建抽象命令类Command
interface Command{
    //定义一个执行的行为
    fun execute()
}
  1. 创建实现者/接收者 程序员Programmer:
//程序员
class Programmer{
    
    //添加功能
    fun addRequirementCommand(){
        System.out.println("需求增加了,加班赶需求!!!")
    }
    
    //删除功能
    fun deleteRequirementCommand(){
        System.out.println("需求不需要要求删除!!!什么!这不是逗我吗!!!!")
    }
    
    //修改功能
    fun reviseRequirementCommand(){
        System.out.println("需求要求修改!!!")
    }
    
    //划水
    fun huashui(){
        System.out.println("上掘金划划水!!!")
    }
}
  1. 创建具体命令
  • 增加需求命令:
class AddRequirementCommand(val xiaocai : Programmer) : Command {
    override fun execute() {
        xiaocai.addRequirementCommand()
    }
}
  • 修改需求命令
class ReviseRequirementCommand(val xiaocai : Programmer) : Command {
    override fun execute() {
        xiaocai.reviseRequirementCommand()

    }
}
  • 删除需求命令
class DeleteRequirementCommand(val xiaocai : Programmer) : Command {
    override fun execute() {
        xiaocai.deleteRequirementCommand()
    }
}
  1. 创建调用者/请求者 老板BossInvoker
class BossInvoker {
    private var _command: Command? = null

    //客户给boss提出需求
    fun setCommand(command: Command) {
        _command = command
    }

    //boss给programmer发出命令
    fun action() {
        _command?.execute()
    }
}
  1. 模拟客户开始提出订单需求:
fun main() {
    //客户找到boos
    val boss = BossInvoker()

    //boss找到小菜
    val xiaocai= Programmer()

    //用户需要增加需求,boss发出增加需求命令
    boss.setCommand(AddRequirementCommand(xiaocai))
    //执行命令
    boss.action()

    //用户需要修改需求,boss发出修改需求命令
    boss.setCommand(ReviseRequirementCommand(xiaocai))
    //执行命令
    boss.action()

    //用户需要删除需求,boss发出删除需求命令
    boss.setCommand(DeleteRequirementCommand(xiaocai))
    //执行命令
    boss.action()

}

输出:

需求增加了,加班赶需求!!!
需求要求修改!!!
需求不需要要求删除!!!什么!这不是逗我吗!!!!

命令模式优缺点

优点:

  • 降低系统的耦合度,命令模式能将调用操作的对象与实现该操作的对象解耦

  • 满足“开闭原则”,对扩展比较灵活

  • 可以实现宏命令。命令模式可以与组合模式结合,将多个命令装配成一个组合命令,即宏命令

  • 方便实现 Undo 和 Redo 操作。命令模式可以与后面介绍的备忘录模式结合,实现命令的撤销与恢复

缺点:

  • 使用命令模式可能会导致某些系统有过多的具体命令类

  • 系统结构更加复杂