ruk·si

🍦 JavaScript Pattern
Command

Updated at 2015-05-13 16:11
var CalculatorCommand = (function() {
  var CalculatorCommand = function(action) {
    this.action = action;
    this.parameters = [].slice.call(arguments, 1);
  };
  CalculatorCommand.prototype.getAction = function() {
    return this.action;
  };
  CalculatorCommand.prototype.getParameters = function() {
    return this.parameters;
  };
  return CalculatorCommand;
})();

var Calculator = (function() {

  var actions = {
    plus: function(memo, value) {
      return memo + value;
    },
    minus: function(memo, value) {
      return memo - value;
    },
    multiply: function(memo, value) {
      return memo * value;
    }
  };

  var Calculator = function() {
    this.pastCommands = [];
  };

  Calculator.prototype.execute = function(command) {
    if (!actions[command.getAction()]) {
      return;
    }
    return this.pastCommands.push(command);
  };

  Calculator.prototype.undo = function() {
    return this.pastCommands.pop();
  };

  Calculator.prototype.getResult = function() {
    var result = 0;
    var commandCount = this.pastCommands.length;
    for (var i = 0; i < commandCount; i++) {
      var command = this.pastCommands[i];
      var params = command.getParameters().slice();
      params.unshift(result);
      result = actions[command.getAction()].apply(this, params);
    }
    return result;
  };

  return Calculator;
})();

var calculator = new Calculator();
console.assert(calculator.getResult() === 0);
console.assert(calculator.execute(new CalculatorCommand('plus', 2)) !== undefined);
console.assert(calculator.getResult() === 2);
console.assert(calculator.execute(new CalculatorCommand('minus', 1)) !== undefined);
console.assert(calculator.getResult() === 1);
console.assert(calculator.execute(new CalculatorCommand('plus', 2)) !== undefined);
console.assert(calculator.getResult() === 3);
console.assert(calculator.execute(new CalculatorCommand('multiply', 3)) !== undefined);
console.assert(calculator.getResult() === 9);
console.assert(calculator.undo() !== undefined);
console.assert(calculator.getResult() === 3);
console.assert(calculator.undo() !== undefined);
console.assert(calculator.getResult() === 1);
console.assert(calculator.undo() !== undefined);
console.assert(calculator.getResult() === 2);
console.assert(calculator.undo() !== undefined);
console.assert(calculator.getResult() === 0);
console.assert(calculator.undo() === undefined);
console.assert(calculator.getResult() === 0);