命令模式最常见的应用场景:有时候需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是什么。此时希望用一种松耦合的方式来设计程序,使得请求发送者和请求接收者能够消除彼此之间的耦合关系。

  1. // 最主要的逻辑就是把命令对象抽象出来,然后就出来了一个command,然后自然而然一个连接目标对象和命令对象的方法就被需要了
  2. var setCommand=function(target,command){
  3. target.onClick=()=>{
  4. command.excute()
  5. }
  6. }
  7. // 一般来说,命令会封装在一个对象里,如:
  8. var MenuBar={
  9. refresh:function(){
  10. console.log('刷新')
  11. }
  12. }
  13. // 针对这种情况,需要把命令对象改造成合适的command的形式供setCommand调用
  14. var refreshMenuBar=function(receiver){
  15. return {
  16. excute:function(){
  17. receiver.refresh()
  18. }
  19. }
  20. }

命令模式最核心的还是:将命令抽象出一个对象,然后随机应变构建出将现有命令与接收命令的对象连接起来的函数。

撤销命令

撤销命令显然需要记录下已经执行过的命令,撤销时从堆栈中依次取出。

命令队列

根据场景的不同,命令的执行表现也不同。有时候命令会在短时间内发出多个,这些命令对象可以依次执行也可以执行最近的一次命令。依次执行的情况下就需要维护一个命令队列。

宏命令

宏命令本身是对基础命令模式的再次组合,无非是在命令对象之后再抽象出一层宏命令对象。

  1. // 自己先实现一个
  2. var macroCommand=function(){
  3. var stack=[]
  4. return {
  5. add:function(command){
  6. stack.push(command)
  7. },
  8. excute:function(){
  9. for(var i=0;i<stack.length;i++){
  10. var curCommand=stack[i]
  11. curCommand.excute()
  12. }
  13. }
  14. }
  15. }
  16. // 书中实现的
  17. var macroCommand=function(){
  18. return {
  19. commandsList:[],
  20. add:function(command){
  21. this.commandsList.push(command)
  22. },
  23. excute:function(){
  24. for(var i=0,command;command=this.commandsList[i++];){
  25. command.excute()
  26. }
  27. }
  28. }
  29. }

傻瓜命令和智能命令

傻瓜命令在命令对象中保存有receiver,这种命令更接近于一种特定化的实例。
智能命令对象中命令是可以直接实现的,和receiver无关。

没有接收者的智能命令,退化到和策略模式非常接近,从代码结构上已经无法分辨它们,能分辨的只有它们的意图的不同。