又有点像多态、策略模式
典型场景:菜单操作、编辑器

  • setCommond函数
  • commond对象
  • receiver接收者
  • commond.execute执行命令

    面向对象的命令模式

    传入commond对象,receiver时commond对象的属性 ```typescript var setCommond = function (button, commond) { button.onclick = function() {
    1. commond.execute();
    } }

var menuBar = { refresh() { console.log(‘刷新菜单目录’); } }

class RefreshMenuBarCommond { constructor(private receiver) {}

execute() { this.receiver.refresh(); } }

var refreshMenuBarCommond = new RefreshMenuBarCommond(menuBar);

setComond(button1, refreshMenuBarCommond);

  1. <a name="sizKA"></a>
  2. # JavaScript的命令模式
  3. receiver作为commond实例的属性 => receiver被封闭在闭包函数环境<br />传入commond实例 => 传入回调函数
  4. ```javascript
  5. // var setCommond
  6. // var menuBar
  7. var RefreshMenuBarCommond = function (receiver) {
  8. return {
  9. execute: () => {
  10. receiver.refresh();
  11. }
  12. }
  13. }
  14. var refreshMenuBarCommond = RefreshMenuBarCommond(menuBar);
  15. setComond(button1, refreshMenuBarCommond);

撤销和重做

撤销一次

undo

  1. class MoveCommond {
  2. constructor(
  3. private receiver,
  4. private pos,
  5. private oldPos = null
  6. ) {}
  7. execute() {
  8. this.receiver.start('left', this.pos);
  9. this.oldPos = this.receiver.dom.getBoundingClientRect().left;
  10. }
  11. undo() {
  12. this.receiver.start('left', this.oldPos);
  13. }
  14. }

撤销一系列命令

把命令储存在一个历史列表
某些情况无法顺利利用undo让对象回到execute之前状态,如Canvas画图、街头霸王游戏。

先清除画布,然后把刚才执行过的命令全部重新执行一遍。 把用户在键盘的输入都封装成命令,存放到堆栈,播放录像时从头开始执行。

命令队列

问题:用户第二次点击button的时候,此时小球的前一个动画可能尚未结束。

命令对象的生命周期跟初始请求发生的时间无关。
当前commond对象的职责完成后,主动通知队列,此时取出正在队列中等待的第一个命令对象,并且执行它。
如何通知队列?

  • 回调函数
  • 发布-订阅模式

宏命令

子命令添加进宏命令对象,迭代依次执行它们的execute方法。

智能命令和傻瓜命令

智能命令,没有接收者,直接把行为交给commond对象;
傻瓜命令:有接收者,由接收者统一负责真正执行客户的请求,如上面的 menuBar

命令模式和策略模式的区别

策略模式:指向的问题域更小,所有策略对象的目标总是一致的,它们只是达到这个目标的不同手段,它们的内部实现是针对“算法”而言的。
智能命令模式:1. 指向的问题域更广,commond对象解决的目标更具发散性。2. 命令模式还可以完成撤销、排队等功能。