前言
命令模式是行为型设计模式
之一;
定义:
将一个请求封装成一个对象,从而让用户使用不同的请求把客户端参数化;对请求排队或者记录日志,以及支持可撤销的操作;
使用场景:
- 需要抽象出待执行的动作,然后以参数的形式提供出来,类似于过程设计中的回调机制,而命令模式正是回调机制的一个面对对象的替代品;
- 在不同的时刻指定、排列和执行请求。一个命令对象可以有与初始请求无关的生存期;
- 需要支持取消操作;
- 支持修改日志功能,这样当系统崩溃时,这些修改可以被重做一遍;
- 需要支持事务操作;
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()
}
- 定义具体命令,
LeftCommand
、TopCommand
、RightCommand
、BottomCommand
/**
* 具体向左命令
*/
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中实现。
总结
优点:
低耦合、灵活的控制性、更好的扩展性;
缺点:
大量类的创建,造成类的膨胀;
结语
如果以上文章对您有一点点帮助,希望您不要吝啬的点个赞加个关注,您每一次小小的举动都是我坚持写作的不懈动力!ღ( ´・ᴗ・` )