Command Design Pattern

The Command Design Pattern is a behavioural design pattern that converts requests or simple operations into objects. This pattern allows us to parametrize objects with operations, queue or log requests, and implement undo/redo. The pattern also provides us with a clear separation between the objects that issue requests and the objects that actually process them.

Definition

In object-oriented programming, the Command Pattern is a design pattern consisting of an object that represents a command, which encapsulates all the information needed to perform a specific action or trigger an event. The main idea behind this pattern is to decouple objects that request an action from the objects that actually perform the action.

Purpose

The main purpose of the Command Design Pattern is to provide a way to decouple objects that request an action from the objects that actually perform the action. This allows us to achieve a separation of concerns and to encapsulate request handling and processing.

The pattern also allows us to implement undo/redo functionality, queue requests for later processing, and execute requests in a specific order.

Benefits

There are several benefits of using the Command Design Pattern:

  1. Encapsulation: The Command Pattern provides a way to encapsulate requests as objects, making it easier to implement undo/redo functionality, queue requests for later processing, and execute requests in a specific order.
  2. Flexibility: The Command Pattern allows us to change the behavior of objects at runtime by passing different commands to them.
  3. Reusability: The Command Pattern makes it easy to reuse request processing code in different parts of the application.
  4. Testability: The Command Pattern makes it easier to test the application as requests can be tested independently of their processing.
  5. Separation of Concerns: The Command Pattern provides a clear separation between objects that issue requests and objects that actually process them.

Command Pattern Implementation Guide (C#)

Step 1: Create an interface called ICommand that defines a single method Execute(). This interface will be used to define the behavior of the commands.

public interface ICommand
{
   void Execute();
}

Step 2: Create concrete commands that implement the ICommand interface. These commands will contain the specific logic for performing the action.

public class ConcreteCommandA : ICommand 
{ 
   private Receiver receiver; 
   
   public ConcreteCommandA(Receiver receiver) 
   { 
      this.receiver = receiver; 
   } 

   public void Execute() 
   { 
      receiver.ActionA(); 
   } 
} 

public class ConcreteCommandB : ICommand 
{ 
   private Receiver receiver; 

   public ConcreteCommandB(Receiver receiver) 
   { 
      this.receiver = receiver; 
   } 

   public void Execute() 
   { 
      receiver.ActionB(); 
   } 
}

Step 3: Create a class called Receiver that contains the methods to be executed by the commands.

public class Receiver 
{ 
   public void ActionA() 
   { 
      Console.WriteLine("ActionA executed"); 
   } 

   public void ActionB() 
   { 
      Console.WriteLine("ActionB executed"); 
   } 
}

Step 4: Create a class called Invoker that contains a list of commands and can execute them.

public class Invoker 
{ 
   private List<ICommand> commands = new List<ICommand>(); 
   
   public void StoreCommand(ICommand command) 
   { 
      this.commands.Add(command); 
   }  

   public void ExecuteCommands() 
   { 
      foreach (ICommand command in commands) 
      { 
         command.Execute(); 
      } 
   } 
}

Step 5: Finally, in the main method, create instances of the Receiver, ConcreteCommandA and ConcreteCommandB classes and set their dependencies. Then, create an instance of the Invoker class and add the commands to it. Finally, call the ExecuteCommands() method on the Invoker instance to execute the commands.

class Program 
{ 
   static void Main(string[] args) 
   { 
      Receiver receiver = new Receiver(); 
      ConcreteCommandA commandA = new ConcreteCommandA(receiver); 
      ConcreteCommandB commandB = new ConcreteCommandB(receiver);
      Invoker invoker = new Invoker(); 
      invoker.StoreCommand(commandA); 
      invoker.StoreCommand(commandB); 
      invoker.ExecuteCommands(); 
   } 
}

Result:

command design pattern result

Conclusion:

The Command Design Pattern is a powerful tool for encapsulating requests as objects and decoupling objects that issue requests from the objects that actually process them.

This pattern makes it easier to implement undo/redo functionality, queue requests for later processing, and execute requests in a specific order.

It also provides a clear separation of concerns, making it easier to maintain and test the application.