JavaScript設計模式--行為型別--命令模式

pengfoo發表於2016-01-27
定義

將請求封裝為物件,從而客戶端可以接收不同的請求物件、佇列或日誌請求作為引數,並支援可撤銷的操作。


使用頻次:5顆星

總結
      命令模式把行為封裝為物件,命令物件將發出請求的物件和實際處理請求的物件區分開來,從而實現鬆耦合設計。這些請求被稱為事件,處理這些請求的程式碼被稱為事件處理器。
     現假設你正在開發一個支援剪下、複製、貼上等滑鼠操作的應用程式。應用中能以不同的方式觸發這些操作,例如一些選單操作或者鍵盤的快捷鍵。

     Command物件可以集中對每一個操作的處理。每個操作對應一個命令。所以剪下、複製、貼上操作分別對應一個命令。 
因為命令集中處理,所以經常出現在一些需要撤銷的應用中。

表示圖


參與者
在這種模式中參與的物件有:


Client--程式碼中的run()函式
引用Receiver物件。


Receiver--程式碼中的Calculator
瞭解如何執行命令
保留執行命令的歷史記錄


Command--程式碼中的Command


Invoker--程式碼中使用者按下按鈕


例子:
在我們的例子中,計算器有四種操作,加減乘除,每種操作被封裝成一個單獨的Command物件。
計算器有個命令堆疊,每種命令執行後被壓入該堆疊中,撤銷操作時,只需要彈出堆疊,執行彈出的命令物件的相反操作的方法。
JS的函式物件(以及回撥)是天然的命令物件,他們能夠像物件一樣傳遞,實際上,他們是本質上也是物件。

log函式助於收集和展示結果。

function add(x, y) { return x + y; }
    function sub(x, y) { return x - y; }
    function mul(x, y) { return x * y; }
    function div(x, y) { return x / y; }

    var Command = function (execute, undo, value) {
        this.execute = execute;
        this.undo = undo;
        this.value = value;
    }

    var AddCommand = function (value) {
        return new Command(add, sub, value);
    };

    var SubCommand = function (value) {
        return new Command(sub, add, value);
    };

    var MulCommand = function (value) {
        return new Command(mul, div, value);
    };

    var DivCommand = function (value) {
        return new Command(div, mul, value);
    };

    var Calculator = function () {
        var current = 0;
        var commands = [];

        function action(command) {
            var name = command.execute.toString().substr(9, 3);
            return name.charAt(0).toUpperCase() + name.slice(1);
        }

        return {
            execute: function (command) {

                current = command.execute(current, command.value);
                commands.push(command);

                log.add(action(command) + ": " + command.value);
            },
            undo: function () {
                var command = commands.pop();
                current = command.undo(current, command.value);

                log.add("Undo " + action(command) + ": " + command.value);
            },
            getCurrentValue: function () {
                return current;
            }
        }
    }

    // log helper
    var log = (function () {
        var log = "";
        return {
            add: function (msg) { log += msg + "\n"; },
            show: function () { alert(log); log = ""; }
        }
    })();


    function run() {

        var calculator = new Calculator();

        // issue commands
        calculator.execute(new AddCommand(100));
        calculator.execute(new SubCommand(24));
        calculator.execute(new MulCommand(6));
        calculator.execute(new DivCommand(2));

        // reverse last two commands
        calculator.undo();
        calculator.undo();

        log.add("\nValue: " + calculator.getCurrentValue());

        log.show();
    }

部落格原文:

http://www.dofactory.com/javascript/command-design-pattern

相關文章