• JavaScript-命令模式


    命令模式

    命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。

    何时使用:在某些场合,比如要对行为进行"记录、撤销/重做、事务"等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将"行为请求者"与"行为实现者"解耦?将一组行为抽象为对象,可以实现二者之间的松耦合。

    如何解决:通过调用者调用接受者执行命令,顺序:调用者→命令→接受者。

    关键代码:定义三个角色:1、received 真正的命令执行对象 2、Command 3、invoker 使用命令对象的入口

    传统的命令模式

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
      </head>
      <body>
        <button id="button1">点击按钮1</button>
        <button id="button2">点击按钮2</button>
        <button id="button3">点击按钮3</button>
        <script>
          const button1 = document.getElementById("button1");
          const button2 = document.getElementById("button2");
          const button3 = document.getElementById("button3");
    
          const MenuBar = {
            refresh() {
              console.log("刷新菜单目录");
            },
          };
    
          const SubMenuBar = {
            add() {
              console.log("增加子菜单");
            },
            del() {
              console.log("删除子菜单");
            },
          };
    
          function setCommand(el, command) {
            el.onclick = function () {
              command.execute();
            };
          }
    
          // 命令对象类,包含execute方法
          // receiver 实际执行动命令的接收者对象
          // key 指示接收者对象里方法名
          class MenuBarCommand {
            constructor(receiver, key) {
              this.receiver = receiver;
              this.key = key;
            }
    
            execute() {
              this.receiver[this.key]();
            }
          }
    
          setCommand(button1, new MenuBarCommand(MenuBar, "refresh"));
          setCommand(button2, new MenuBarCommand(SubMenuBar, "add"));
          setCommand(button3, new MenuBarCommand(SubMenuBar, "del"));
        </script>
      </body>
    </html>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    JavaScript版本使用闭包和高阶函数实现带有历史记录的命令模式

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>命令模式-街头霸王</title>
      </head>
      <body>
        <button id="replay">播放录像</button>
        <script>
          const Ryu = {
            attack() {
              console.log("攻击");
            },
            defense() {
              console.log("防御");
            },
            jump() {
              console.log("跳跃");
            },
            crouch() {
              console.log("蹲下");
            },
          };
          // 使用闭包创建命令
          const makeCommand = function (receiver, state) {
            return function () {
              receiver[state]();
            };
          };
          const commands = {
            119: "jump", // W
            115: "crouch", // S
            97: "defense", // A
            100: "attack", // D
          };
    
    	  // 保存历史命令记录
          const commandStack = [];
    
          document.onkeypress = function (ev) {
            const keyCode = ev.keyCode;
            const command = makeCommand(Ryu, commands[keyCode]);
    
            if (command) {
              commandStack.push(command);
              command();
            }
          };
    
          document.getElementById("replay").onclick = function () {
            let command;
            while ((command = commandStack.shift())) {
              command();
            }
          };
        </script>
      </body>
    </html>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
  • 相关阅读:
    C++ priority_queue如何自定义比较函数?和sort里面自定义比较函数有何区别?
    vue3源码分析——手写diff算法
    knative入门指南
    TCP三次握手和四次挥手(彻底弄明白)
    2023年【化工自动化控制仪表】最新解析及化工自动化控制仪表作业考试题库
    【论文阅读】ICLR 2022: Scene Transformer: A unified architecture for predicting future trajectories of multiple agents
    Spark编程:combineByKey与aggregateByKey异同
    游戏设计模式专栏(十三):在Cocos游戏开发中运用责任链模式
    K-means和DBSCAN
    C++:二叉树进阶
  • 原文地址:https://blog.csdn.net/qq_42372534/article/details/124594042