js设计模式--命令模式

前言

本系列文章主要根据《JavaScript设计模式与开发实践》整理而来,其中会加入了一些本身的思考。但愿对你们有所帮助。html

文章系列

js设计模式--单例模式segmentfault

js设计模式--策略模式设计模式

js设计模式--代理模式函数

js设计模式--迭代器模式ui

js设计模式--发布订阅模式this

概念

命令模式中的命令(command)指的是一个执行某些特定事情的指令。prototype

场景

有时候须要向某些对象发送请求,可是并不知道请求的接收 者是谁,也不知道被请求的操做是什么。
如快餐店点餐,咱们不须要知道厨师是谁,咱们只须要把订单交给服务员设计

优缺点

请求发送者和请求接收者可以消除彼此之间的耦合关系代理

例子

按钮点击

简单的实现

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>

<body>
  <button id="button1">点击按钮1</button>

  <script>
    var button1 = document.getElementById('button1')

    button1.onclick = function () {
      console.log('刷新菜单目录');
    }
  </script>
</body>

</html>

若是这个点击事件实现很复杂,须要多人合做完成,那咱们不得不深刻到button1.onclick内部去修改代码,违背了开放封闭原则code

命令模式实现

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>

<body>
  <button id="button1">点击按钮1</button>

  <script>
    var button1 = document.getElementById('button1')


    var setCommand = function (button, command) {
      button.onclick = function () {
        command.execute();
      }
    };

    var MenuBar = {
      refresh: function () {
        console.log('刷新菜单目录');
      }
    };

    var RefreshMenuBarCommand = function (receiver) {
      this.receiver = receiver;
    };
    RefreshMenuBarCommand.prototype.execute = function () {
      this.receiver.refresh();
    };

    var refreshMenuBarCommand = new RefreshMenuBarCommand(MenuBar);
    setCommand(button1, refreshMenuBarCommand);
  </script>
</body>

</html>

JavaScript 做为将函数做为一等对象的语言,跟策略模式同样,命令模式也早已融入到了 JavaScript 语言之中。

js中的命令模式

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>

<body>
  <button id="button1">点击按钮1</button>

  <script>
    var button1 = document.getElementById('button1')

    var setCommand = function (button, fn) {
      button.onclick = fn
    };

    var MenuBar = {
      refresh: function () {
        console.log('刷新菜单目录');
      }
    };

    setCommand(button1, MenuBar.refresh)
  </script>
</body>

</html>

设置背景色的例子

撤销命令

咱们如今来实现一个撤销操做的例子:
界面上有四个按钮,三个能够设置不一样的背景色,undo按钮能够撤销上一次的操做

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>

<body>
  <div id="div" style="height: 100px;width: 100px;background-color: blue"></div>
  <button id="button1">red</button>
  <button id="button2">black</button>
  <button id="button3">yellow</button>
  <button id="undo">undo</button>

  <script>
    var button1 = document.getElementById('button1')
    var button2 = document.getElementById('button2')
    var button3 = document.getElementById('button3')
    var undo = document.getElementById('undo')
    var div = document.getElementById('div')

    var cacheColor = []
    var setCommand = function (button, fn) {
      button.onclick = fn
    };

    var commond = {
      cache: [],
      receiver: null,
      execute(newBgColor) {
        this.cache.push(this.receiver.style.backgroundColor)
        this.receiver.style.backgroundColor = newBgColor
      },
      undo() {
        var oldBgColor = this.cache.pop()
        this.receiver.style.backgroundColor = oldBgColor
      },
      setReceiver(target) {
        this.receiver = target
      }
    }

    commond.setReceiver(div)
    button1.onclick = function () {
      commond.execute('red')
    }
    button2.onclick = function () {
      commond.execute('black')
    }
    button3.onclick = function () {
      commond.execute('yellow')
    }
    undo.onclick = function () {
      commond.undo()
    }
  </script>
</body>

</html>

重作操做

这里咱们增长一个redo按钮,以恢复以前的操做,须要一个currentIndex来记录当前的索引

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>

<body>
  <div id="div" style="height: 100px;width: 100px;background-color: blue"></div>
  <button id="button1">red</button>
  <button id="button2">black</button>
  <button id="button3">yellow</button>
  <button id="undo">undo</button>
  <button id="redo">redo</button>

  <script>
    var button1 = document.getElementById('button1')
    var button2 = document.getElementById('button2')
    var button3 = document.getElementById('button3')
    var undo = document.getElementById('undo')
    var div = document.getElementById('div')

    var commond = {
      cache: [],
      currentIndex: 0,
      receiver: null,
      execute(newBgColor) {
        this.receiver.style.backgroundColor = newBgColor
        this.currentIndex++
        this.cache.push(newBgColor)
        console.log('execute:', this.cache, this.currentIndex)
      },
      undo() {
        if (this.currentIndex <= 0) return
        var oldBgColor = this.cache[--this.currentIndex]
        this.receiver.style.backgroundColor = oldBgColor
        console.log('undo:', this.cache, this.currentIndex)
      },
      redo() {
        if (this.currentIndex >= this.cache.length - 1) return
        var preBgColor = this.cache[this.currentIndex + 1]
        this.currentIndex++
        this.receiver.style.backgroundColor = preBgColor
        console.log('redo:', this.cache, this.currentIndex)
      },
      setReceiver(target) {
        this.receiver = target
        this.cache.push(this.receiver.style.backgroundColor)
        console.log('setReceiver:', this.cache, this.currentIndex)
      }
    }

    commond.setReceiver(div)
    button1.onclick = function () {
      commond.execute('red')
    }
    button2.onclick = function () {
      commond.execute('black')
    }
    button3.onclick = function () {
      commond.execute('yellow')
    }
    undo.onclick = function () {
      commond.undo()
    }
    redo.onclick = function () {
      commond.redo()
    }
  </script>
</body>

</html>
相关文章
相关标签/搜索