
Command design pattern encapsulates request as an object thereby allowing parameterize other objects with different request, log and queue requests, and support undoable operations.

Test client:
[TestFixture] public class CommandPatternTest { private Calculator _calculator; private Invoker<int> _invoker; [SetUp] public void SetUp() { //Arrange _calculator = new Calculator(); _invoker = new Invoker<int>(); } [TestCase(1, 2, 3)] public void InvokedAddCommand_OnValidParams_ReturnsExpectedResult(int a, int b, int expectedResult) { //Arrange var addCommand = new AddCommand<int>(_calculator, a, b); //Act var actualResult = _invoker.SetAndExecuteCommand(addCommand); //Assert Assert.AreEqual(expectedResult, actualResult); } [TestCase(3, 2, 1)] public void InvokedSubtractCommand_OnValidParams_ReturnsExpectedResult(int a, int b, int expectedResult) { //Arrange var subtractCommand = new SubtractCommand<int>(_calculator, a, b); //Act var actualResult = _invoker.SetAndExecuteCommand(subtractCommand); Assert.AreEqual(expectedResult, actualResult); } [TestCase(1, 2, 3)] public void InvokedUndo_ReturnsExpectedResult(int a, int b, int expectedResult) { //Arrange var addCommand = new AddCommand<int>(_calculator, 1, 2); _invoker.SetAndExecuteCommand(addCommand); _invoker.SetAndExecuteCommand(addCommand); //Act var actualResult = _invoker.Undo(); //Assert Assert.AreEqual(expectedResult, actualResult); } }
Invoker:
////// The Invoker holds a command and calls command's execute method /// /// public class Invoker where T : struct, IConvertible, IComparable { private Stack<ICalculatorCommand> _commands = new Stack<ICalculatorCommand>(); public void SetCommand(ICalculatorCommand command) { _commands.Push(command); } public T SetAndExecuteCommand(ICalculatorCommand command) { _commands.Push(command); return command.Calculate(); } public T Execute() { return _commands.Peek().Calculate(); } public T Undo() { if (!_commands.Any()) throw new InvalidOperationException(); _commands.Pop(); return _commands.Peek().Calculate(); } }
Receiver:
public enum Operand { Add = '+', Subtract = '-' } ////// A commands receiver, performs real actions /// public class Calculator { public dynamic PerformCalculation(Operand operand, dynamic arg1, dynamic arg2) { switch (operand) { case Operand.Add: return arg1 + arg2; case Operand.Subtract: return arg1 - arg2; } return null; } }
Abstract command:
public interface ICalculatorCommand where T : struct, IConvertible, IComparable { T Calculate(); }
Concrete commands
public class AddCommand : ICalculatorCommand where T : struct, IConvertible, IComparable { private Calculator _calculator; private T _arg1, _arg2; public AddCommand(Calculator calculator, T arg1, T arg2) { _calculator = calculator; _arg1 = arg1; _arg2 = arg2; } public T Calculate() { return (T)_calculator.PerformCalculation(Operand.Add, _arg1, _arg2); } }
public class SubtractCommand : ICalculatorCommand where T : struct, IConvertible, IComparable { private Calculator _calculator; private T _arg1, _arg2; public SubtractCommand(Calculator calculator, T arg1, T arg2) { _calculator = calculator; _arg1 = arg1; _arg2 = arg2; } public T Calculate() { return (T)_calculator.PerformCalculation(Operand.Subtract, _arg1, _arg2); } }