Command Design Pattern

Introduction:
Command Design Pattern enables you to encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.
Example:
The below code demonstrates the Command pattern to be used on a simple calculator. This caluclator doing unlimited number of undo’s & Redo’s .

One thing we might do to extend this Calculator project, is to create an IOperator Interface and for each operation have a concret Operator Class. for simplicity I am not going to do this. I will hard code couple of operator to make it very simple to be understood.

 

CommandDesignPattern

 

static void Main()
{
// Create user and let her compute
User user = new User();
// User presses calculator buttons
user.Calculate(‘+’, 100);
user.Calculate(‘-‘, 50);
user.Calculate(‘*’, 10);
user.Calculate(‘/’, 2);
// Undo 4 commands
user.UndoCalculation(4);
// Redo 3 commands
user.RedoCalculation(3);
// Wait for user
Console.ReadKey();
}
interface ICommand
{
void Execute();
void UnExecute();
}
class CalculationCommand : ICommand
{
private char _operator;
private int _operand;
private Calculator _calculator;
// Constructor
public CalculationCommand(Calculator calculator,
char @operator, int operand)
{
this._calculator = calculator;
this._operator = @operator;
this._operand = operand;
}
// Gets operator
public char Operator
{
set { _operator = value; }
}
// Get operand
public int Operand
{
set { _operand = value; }
}
// Execute new command
publicĀ  void Execute()
{
_calculator.Operation(_operator, _operand);
}
// Unexecute last command
publicĀ  void UnExecute()
{
_calculator.Operation(Undo(_operator), _operand);
}
// Returns opposite operator for given operator
private char Undo(char @operator)
{
switch (@operator)
{
case ‘+’: return ‘-‘;
case ‘-‘: return ‘+’;
case ‘*’: return ‘/’;
case ‘/’: return ‘*’;
default: throw new
ArgumentException(“@operator”);
}
}
}
class Calculator
{
private int _currentIndex = 0;
public void Operation(char @operator, int operand)
{
switch (@operator)
{
case ‘+’: _currentIndex += operand; break;
case ‘-‘: _currentIndex -= operand; break;
case ‘*’: _currentIndex *= operand; break;
case ‘/’: _currentIndex /= operand; break;
}
Console.WriteLine(
“Current value = {0,3} (following {1} {2})”,
_currentIndex, @operator, operand);
}
}
class User
{
// Initializers
private Calculator _calculator = new Calculator();
private List<ICommand> _commands = new List<ICommand>();
private int _currentIndex = 0;
public void RedoCalculation(int levels)
{
Console.WriteLine(“\n—- Redo {0} levels “, levels);
// Perform redo operations
for (int i = 0; i < levels; i++)
{
if (_currentIndex < _commands.Count – 1)
{
ICommand command = _commands[_currentIndex++];
command.Execute();
}
}
}
public void UndoCalculation(int levels)
{
Console.WriteLine(“\n—- Undo {0} levels “, levels);
// Perform undo operations
for (int i = 0; i < levels; i++)
{
if (_currentIndex > 0)
{
ICommand command = _commands[–_currentIndex] as ICommand;
command.UnExecute();
}
}
}
public void Calculate(char @operator, int operand)
{
// Create command operation and execute it
ICommand command = new CalculationCommand(
_calculator, @operator, operand);
command.Execute();
// Add command to undo list
_commands.Add(command);
_currentIndex++;
}
}

Download Code

Leave a Reply

Your email address will not be published.