Android设计模式详解之命令模式

前言

命令模式是行为型设计模式之一;

定义:将一个请求封装成一个对象,从而让用户使用不同的请求把客户端参数化;对请求排队或者记录日志,以及支持可撤销的操作;

使用场景:

  • 需要抽象出待执行的动作,然后以参数的形式提供出来,类似于过程设计中的回调机制,而命令模式正是回调机制的一个面对对象的替代品;
  • 在不同的时刻指定、排列和执行请求。一个命令对象可以有与初始请求无关的生存期;
  • 需要支持取消操作;
  • 支持修改日志功能,这样当系统崩溃时,这些修改可以被重做一遍;
  • 需要支持事务操作;

UML类图:
命令模式UML类图

  • Client:客户端角色;
  • Invoker:请求者角色;
    该类的职责就是调用命令对象执行具体的请求,相关的方法我们称为行动方法;
  • Receiver:接收者角色;
    该类负责具体实施或执行一个请求,执行具体逻辑的角色,具体操作逻辑的方法我们称为行动方法;
  • Command:命令角色;
    定义所有具体命令类的抽象接口;
  • ConcreteCommand:具体命令角色;
    该类实现了Command接口,在execute方法中调用接收者角色的相关方法,在接收者和命令执行的具体行为之间加以弱耦合。

通用模板代码

  • 定义接收者角色,Receiver
/**
 * 接收者类
 */
class Receiver {
    //最终执行具体命令逻辑的方法
    fun action() {
        println("执行具体操作")
    }
}
  • 定义抽象命令接口,Command
/**
 * 抽象命令接口
 */
interface Command {
    //执行具体操作的命令
    fun execute()
}
  • 定义具体命令类,ConcreteCommand
/**
 * 具体命令类
 * @param receiver 持有一个接收者对象的引用
 */
class ConcreteCommand(private var receiver: Receiver) : Command {
    override fun execute() {
        //调用接收者的相关方法执行具体逻辑
        receiver.action()
    }

}
  • 定义请求者类,Invoker
/**
 * 请求者类
 * @param command 持有一个对命令对象的引用
 */
class Invoker(private val command: Command) {
    fun action() {
        //调用具体命令对象的相关方法,执行具体命令
        command.execute()
    }
}
  • 编写调用测试类,相当于Client角色
/**
 * 相当于Client类
 */
object Test {

    @JvmStatic
    fun main(args: Array<String>) {
        //构造一个接收者对象
        val receiver = Receiver()
        //根据接收者对象构造一个命令对象
        val concreteCommand = ConcreteCommand(receiver)
        //根据命令对象构造一个请求者对象
        val invoker = Invoker(concreteCommand)
        //执行请求方法
        invoker.action()
    }
}

实现实例

这里我们以游戏中上下左右四个按键进行举例四个按键即对应四个命令,分别按下对应向左向右向上向下命令,这里我们使用命令模式来实现;

  • 首先,定义命令接收者,即最终执行命令的对象,CommandReceiver

/**
 * 命令接收者对象
 */
class CommandReceiver {

    fun toLeft() {
        println("向左")
    }

    fun toTop() {
        println("向上")
    }

    fun toRight() {
        println("向右")
    }


    fun toBottom() {
        println("向下")
    }
}
  • 定义抽象命令,Command
/**
 * 抽象命令
 */
interface Command {
   fun execute()
}
  • 定义具体命令,LeftCommandTopCommandRightCommandBottomCommand
/**
 * 具体向左命令
 */
class LeftCommand(private val commandReceiver: CommandReceiver) : Command {

    override fun execute() {
        commandReceiver.toLeft()
    }
}

/**
 * 具体向上命令
 */
class TopCommand(private val commandReceiver: CommandReceiver) : Command {

    override fun execute() {
        commandReceiver.toTop()
    }
}

/**
 * 具体向右命令
 */
class RightCommand(private val commandReceiver: CommandReceiver) : Command {

    override fun execute() {
        commandReceiver.toRight()
    }
}

/**
 * 具体向下命令
 */
class BottomCommand(private val commandReceiver: CommandReceiver) : Command {

    override fun execute() {
        commandReceiver.toBottom()
    }
}
  • 定义命令发起者,CommandInvoker
/**
 * 命令请求者
 */
class CommandInvoker {

    private var leftCommand: LeftCommand? = null
    private var topCommand: TopCommand? = null
    private var rightCommand: RightCommand? = null
    private var bottomCommand: BottomCommand? = null

    fun setLeftCommand(leftCommand: LeftCommand) {
        this.leftCommand = leftCommand
    }

    fun setTopCommand(topCommand: TopCommand) {
        this.topCommand = topCommand
    }

    fun setRightCommand(rightCommand: RightCommand) {
        this.rightCommand = rightCommand
    }

    fun setBottomCommand(bottomCommand: BottomCommand) {
        this.bottomCommand = bottomCommand
    }

    /**
     * 请求执行向左命令
     */
    fun executeLeftAction() {
        leftCommand?.execute()
    }

    /**
     * 请求执行向上命令
     */
    fun executeTopAction() {
        topCommand?.execute()
    }

    /**
     * 请求执行向右命令
     */
    fun executeRightAction() {
        rightCommand?.execute()
    }

    /**
     * 请求执行向下命令
     */
    fun executeBottomAction() {
        bottomCommand?.execute()
    }
}
  • 编写测试类进行验证;
object Test {

    @JvmStatic
    fun main(args: Array<String>) {
        //构造一个接收者对象
        val receiver = CommandReceiver()
        //根据接收者对象构造一个命令对象
        val leftCommand = LeftCommand(receiver)
        val topCommand = TopCommand(receiver)
        val rightCommand = RightCommand(receiver)
        val bottomCommand = BottomCommand(receiver)
        //根据命令对象构造一个请求者对象
        val invoker = CommandInvoker()
        invoker.setLeftCommand(leftCommand)
        invoker.setTopCommand(topCommand)
        invoker.setRightCommand(rightCommand)
        invoker.setBottomCommand(bottomCommand)
        //执行 `上上下下左右左右`
        invoker.executeTopAction()
        invoker.executeTopAction()
        invoker.executeBottomAction()
        invoker.executeBottomAction()
        invoker.executeLeftAction()
        invoker.executeRightAction()
        invoker.executeLeftAction()
        invoker.executeRightAction()
    }


}

前面我们有提到过,命令模式支持修改日志和事务操作,如上面例子,我们可以在CommandInvoker类中记录每一步执行的操作进行日志记录,同时也可以根据记录的操作进行事务提交;

Android源码中的命令模式

  • Application Framework(应用程序框架层)中PackageManagerService类(包管理部分)也用到了命令模式。PackageManagerService是Android系统的Service之一,主要功能是实现对应用包的解析、管理、卸载等操作。具体的包的安装、移动以及包大小的测量分别在3个具体子类InstallParams、MoveParams和MeasureParams中实现。

总结

优点:
低耦合、灵活的控制性、更好的扩展性;

缺点:
大量类的创建,造成类的膨胀;

结语

如果以上文章对您有一点点帮助,希望您不要吝啬的点个赞加个关注,您每一次小小的举动都是我坚持写作的不懈动力!ღ( ´・ᴗ・` )

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值