Introduction

A Command Design pattern is a behavioural design pattern. In which a request can be turned to action.

Where to use a Command Design Pattern?

When we want to,
  • Do/undo action
  • When you want to pass a method as an argument or when you want call callbackfunction
  • When you want to log or track commands

Why use a Command Design Pattern?

Command Design Pattern is a request-driven design pattern. A request will help to choose which command needs to get executed without knowing which object.method to call. In this case, command design patterns play a key role which will make this easy by using ICommand. A Command design pattern actually decouples command manager and command execution logic i.e. Actual implementation.
Players in this pattern:
  • ICommand – its interface which will do action undo action
  • ConcreateCommand – it’s one who implements ICommand
  • Invoker – One who carries out the action
  • Receiver: One who receives action from invoker and perform action
Example
Problem definition - Provide an interface to the user to open and close the door. And if the user wants, they should be able to undo his/her last action.
This example actually showcases the use case of Do and undo action requirement. For other requirements, I will write separate articles.
In this:
  • ICommand – ICommand
  • ConcreateCommand – DoorCommand
  • Invoker – client, in our case we will client operation in main function
  • Receiver – Door
Below is the ICommand interface which will define contact to implement:
  1. namespace Command.Design.Pattern
  2. {
  3. public interface ICommand
  4. {
  5. void Execute(Action action);
  6. void UndoExecute();
  7. }
  8. }
We will create enum for peroming Action
  1. public enum Action
  2. {
  3. DOOR_OPEN,
  4. DOOR_CLSOE
  5. }
Below is the DoorCommand class which implements the ICommand contract :
  1. namespace Command.Design.Pattern
  2. {
  3. public class DoorCommand : ICommand
  4. {
  5. private readonly Door door;
  6. Action lastAction { get; set; }
  7. public DoorCommand()
  8. {
  9. door = new Door();
  10. }
  11. public void Execute(Action doorAction)
  12. {
  13. switch (doorAction)
  14. {
  15. case Action.DOOR_OPEN:
  16. door.Open();
  17. break;
  18. case Action.DOOR_CLSOE:
  19. door.Close();
  20. break;
  21. default:
  22. return;
  23. }
  24. lastAction = doorAction;
  25. }
  26. public void UndoExecute()
  27. {
  28. switch (lastAction)
  29. {
  30. case Action.DOOR_OPEN:
  31. door.Close();
  32. break;
  33. case Action.DOOR_CLSOE:
  34. door.Open();
  35. break;
  36. default:
  37. return;
  38. }
  39. }
  40. }
  41. }
Below is the Door class, it actually has core logic implementation:
  1. using static System.Console;
  2. namespace Command.Design.Pattern
  3. {
  4. public class Door
  5. {
  6. public void Open() => WriteLine("------------Door Opened---------------");
  7. public void Close()=> WriteLine("------------Door Closed---------------");
  8. }
  9. }
Below is the Invoker, which requests some action:
  1. using static System.Console;
  2. namespace Command.Design.Pattern
  3. {
  4. class Home
  5. {
  6. static void Main(string[] args)
  7. {
  8. ICommand command = new DoorCommand();
  9. command.Execute(Action.DOOR_OPEN);
  10. command.Execute(Action.DOOR_CLSOE);
  11. command.UndoExecute();
  12. ReadLine();
  13. }
  14. }
  15. }
Below is the output window:

Summary

In this article, we learned of usage of the command design pattern, mainly concentrating on the do and undo operation.