96 lines
		
	
	
	
		
			2.5 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			96 lines
		
	
	
	
		
			2.5 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
---
 | 
						|
title: Command pattern
 | 
						|
categories:
 | 
						|
  - DSA
 | 
						|
tags:
 | 
						|
  - design-patterns
 | 
						|
---
 | 
						|
 | 
						|
# Command pattern
 | 
						|
 | 
						|
This is typically used when you want to sequence a fairly large number of actions in a series with the option to undo or reverse them. Similarly to the mediator it has a one-to-many architecture (there is a central class that sequences the commands which are handled by other classes) but in addition to sending and routing requests between colleagues, it keeps a central store of them and can reverse actions.
 | 
						|
 | 
						|
The typical example is a calculator. Will will generate this using constructor function syntax, rather than ES6 class syntax.
 | 
						|
 | 
						|
You have a bunch of arithmetic functions:
 | 
						|
 | 
						|
```jsx
 | 
						|
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;
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
Then a generalised `Command` class that has three parameters: undo, execute, and return a value:
 | 
						|
 | 
						|
```jsx
 | 
						|
var Command = function (execute, undo, value) {
 | 
						|
  this.execute = execute;
 | 
						|
  this.undo = undo;
 | 
						|
  this.value = value;
 | 
						|
};
 | 
						|
```
 | 
						|
 | 
						|
We then create the specific commands by combining the functions and the `Command` class:
 | 
						|
 | 
						|
```jsx
 | 
						|
var AddCommand = function (value) {
 | 
						|
  return new Command(add, sub, value);
 | 
						|
};
 | 
						|
 | 
						|
// We would create one of these classes for each of the four operations
 | 
						|
```
 | 
						|
 | 
						|
So now the `add` and `subtract` functions slot into `execute` and `undo` on the `Command` class.
 | 
						|
 | 
						|
Finally we create the centralised command class that will return values based on the individual commands it sequences and issues, store them and remove them:
 | 
						|
 | 
						|
```jsx
 | 
						|
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;
 | 
						|
        }
 | 
						|
    }
 | 
						|
```
 | 
						|
 | 
						|
```jsx
 | 
						|
calculator.execute(new AddCommand(100));
 | 
						|
calculator.execute(new SubCommand(24));
 | 
						|
calculator.execute(new MulCommand(6));
 | 
						|
calculator.execute(new DivCommand(2));
 | 
						|
```
 | 
						|
 | 
						|
Or undo them with:
 | 
						|
 | 
						|
```jsx
 | 
						|
calculator.undo();
 | 
						|
```
 |