模式名称:命令模式
模式分类:行为型
模式意图:将一个请求封装为一个对象,从而使得可以用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可撤销的操作。
结构图:
适用于:
1、抽象出待执行的动作以参数化某对象。Command 模式是过程语言中的回调(Callback)机制的一个面向对象的替代品。
2、在不同的时刻指定、排列和执行请求。一个 Command 对象可以有一个与初始请求无关的生存期。如果一个请求的接收者可用一种与地址空间无关的方式表达,那么就可以将负责该请求的命令对象传递给另一个不同的进程并在那儿实现该请求。
3、支持取消操作。Command 的 Execute 操作可在实施操作前将状态存储起来,在取消操作时这个状态用来消除该操作的影响。Command 接口必须添加一个 Unexecute 操作,该操作取消上一次 Execute 调用的效果。执行的命令被存储在一个历史列表中。可通过向后和向前遍历这一列表并分别调用Unexecute和Execute来实现重数不限的“取消和“重做”。
4、支持修改日志。这样当系统崩溃时,这些修改可以被重做一遍。在 Command 接口中添加装载操作和存储操作,可以用来保持变动的一个一致的修改日志。从崩溃中恢复的过程包括从磁盘中重新读入记录下来的命令并用 Execute 操作重新执行它们。
5、用构建在原语操作上的高层操作构造一个系统。这样一种结构在支持事务(Transaction)的信息系统中很常见。Command 模式提供了对事务进行建模的方法。Command有一个公共接口,使得可以用同一种方式调用所有的事务,同时使用该模式也易于添加新事务以扩展系统。
命令模式一般不单独使用,可能会配合责任链模式或者解释器模式等等。当前先简单引入,实现简单功能,后面配合其他模式看看会有什么妙用。
意图:将一个请求(命令)封装为一个对象,统一成execute执行,对请求(命令)排队或记录请求(命令)日志,以及支持可撤销的操作。
?命令类接口
export interface ICommand {
execute(): void;
}
// 具体攻击命令类
export class AttackCommand implements ICommand {
unitItem: UnitItem<any>
constructor(unitItem: UnitItem<any>) {
this.unitItem = unitItem;
}
execute(): void {
console.log('AttackCommand execute')
this.unitItem.attack(this.unitItem.targetUnitItem);
}
}
// 具体防御命令类
export class DefendCommand implements ICommand {
unitItem: UnitItem<any>
constructor(unitItem: UnitItem<any>) {
this.unitItem = unitItem;
}
execute(): void {
console.log('DefendCommand execute')
this.unitItem.idle(); // 临时随便写个
}
}
命令队列类
export class CommandQueue {
private commands: ICommand[] = [];
addCommand(command: ICommand): void {
this.commands.push(command);
}
executeCommands(): void {
for (const command of this.commands) {
command.execute();
}
this.commands = [];
}
}
let unitItem1 = xhgame.itemFactory.createUnitItem('kuloubing')
let unitItem2 = xhgame.itemFactory.createUnitItem('kuloubing')
unitItem1.targetUnitItem = unitItem2
const attackCommand = new AttackCommand(unitItem1);
const defendCommand = new DefendCommand(unitItem1);
// 创建命令队列
const commandQueue = new CommandQueue();
// 将命令添加到队列中
commandQueue.addCommand(attackCommand);
commandQueue.addCommand(defendCommand);
// 执行命令队列中的命令
commandQueue.executeCommands();
有了命令模式,后面一节尝试配合责任链模式会有什么妙用