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>

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>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值