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:
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:
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:
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:
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.
Top comments (0)