What is Command Pattern in C#?
Tags: csharp
Published: 2024-01-26 07:57:47

The Command Pattern is a behavioral design pattern that enables encapsulating method invocation, requests, or operations into a single object. This object acts as a command, decoupling the sender and receiver of the request. In C#, this pattern provides a way to parameterize clients with commands, queue or log requests, and support undoable operations.

To understand the Command Pattern, let's consider a hypothetical scenario of a text editor application. Our application has various document editing operations such as copy, paste, cut, and undo. We can implement these operations using the Command Pattern. 

First, we will create an interface called ICommand, which defines an Execute() method for executing the command and an Undo() method for undoing the command:

```csharp
public interface ICommand
{
    void Execute();
    void Undo();
}
```

Next, we will create concrete command classes that implement the ICommand interface for each operation. Let's say we have classes for CopyCommand, PasteCommand, CutCommand, and UndoCommand:

```csharp
public class CopyCommand : ICommand
{
    private string _text;

    public CopyCommand(string text)
    {
        _text = text;
    }

    public void Execute()
    {
        // Logic to copy the text
        Console.WriteLine("Copying: " + _text);
    }

    public void Undo()
    {
        // Logic to undo the copy operation
        Console.WriteLine("Undoing Copy: " + _text);
    }
}

// Similarly, we can implement the other command classes for Paste, Cut, and Undo operations
```

Now, we can have a invoker or client class that accepts these concrete command objects and executes them. Let's call this class TextEditor:

```csharp
public class TextEditor
{
    private ICommand _command;

    public void SetCommand(ICommand command)
    {
        _command = command;
    }

    public void ExecuteCommand()
    {
        _command.Execute();
    }

    public void UndoCommand()
    {
        _command.Undo();
    }
}
```

Finally, let's see how we can use the Command Pattern in the client code:

```csharp
static void Main(string[] args)
{
    TextEditor textEditor = new TextEditor();

    // Creating the commands
    ICommand copyCommand = new CopyCommand("Hello World");
    ICommand pasteCommand = new PasteCommand();
    ICommand cutCommand = new CutCommand();
    ICommand undoCommand = new UndoCommand();

    // Setting/assigning the commands
    textEditor.SetCommand(copyCommand);

    // Executing the command
    textEditor.ExecuteCommand(); // Output: Copying: Hello World

    // Setting the new command
    textEditor.SetCommand(pasteCommand);

    // Executing the new command
    textEditor.ExecuteCommand(); // Output: Pasting

    // Undoing the previous command
    textEditor.UndoCommand(); // Output: Undoing Paste

    // Setting the cut command
    textEditor.SetCommand(cutCommand);

    // Executing the cut command
    textEditor.ExecuteCommand(); // Output: Cutting

    // Setting the undo command
    textEditor.SetCommand(undoCommand);

    // Executing the undo command
    textEditor.ExecuteCommand(); // Output: Undoing Cut
}
```

By utilizing the Command Pattern, we can easily add new command classes or modify existing ones without affecting other parts of the application. Furthermore, we can easily implement features like logging, queuing, and macro recording by tracking and managing the executed commands.

In conclusion, the Command Pattern provides a way to encapsulate method invocation as objects, allowing us to implement complex command structures and handle them dynamically at runtime. It promotes loose coupling between objects and enables the separation of responsibilities, making the code more maintainable and extensible.