Command Pattern
Part of the Object Oriented Programming section of Coddy's C# journey — lesson 56 of 70.
The Command pattern is a behavioral pattern that turns a request into a stand-alone object containing all information about the request. This transformation lets you pass requests as method arguments, queue them, log them, or support undoable operations.
The pattern separates the object that invokes an operation from the object that knows how to perform it. It consists of four key components: a command interface, concrete commands, a receiver (the object that does the actual work), and an invoker (the object that triggers commands).
public interface ICommand
{
void Execute();
}
public class Light // Receiver
{
public void TurnOn() => Console.WriteLine("Light is ON");
public void TurnOff() => Console.WriteLine("Light is OFF");
}
public class TurnOnCommand : ICommand
{
private Light _light;
public TurnOnCommand(Light light) => _light = light;
public void Execute() => _light.TurnOn();
}
public class TurnOffCommand : ICommand
{
private Light _light;
public TurnOffCommand(Light light) => _light = light;
public void Execute() => _light.TurnOff();
}The invoker stores and executes commands without knowing what they do:
public class RemoteControl // Invoker
{
private ICommand _command;
public void SetCommand(ICommand command) => _command = command;
public void PressButton() => _command.Execute();
}
// Usage
var light = new Light();
var remote = new RemoteControl();
remote.SetCommand(new TurnOnCommand(light));
remote.PressButton(); // Light is ON
remote.SetCommand(new TurnOffCommand(light));
remote.PressButton(); // Light is OFFThe Command pattern is particularly powerful for implementing undo functionality, macro recording, or queuing operations for later execution. Each command encapsulates everything needed to perform an action, making your system more flexible and extensible.
Challenge
EasyLet's build a text editor command system using the Command pattern. You'll create a system where editing operations like inserting and deleting text are encapsulated as command objects, allowing the editor to execute them through a unified interface.
You'll organize your code across three files:
Command.cs: Define anICommandinterface in theTextEditornamespace with a single methodExecute(). Then create two concrete command classes:InsertCommand- takes aDocumentand a stringtextin its constructor. When executed, it appends the text to the document and printsInserted: {text}DeleteCommand- takes aDocumentand anint countin its constructor. When executed, it removes the lastcountcharacters from the document and printsDeleted: {count} characters
Document.cs: Create aDocumentclass in the same namespace. This is your receiver - the object that actually performs the text operations. It should have:- A private string field to store the content (initialize to empty string)
- An
Append(string text)method that adds text to the content - A
RemoveLast(int count)method that removes the lastcountcharacters (if count exceeds content length, clear all content) - A
GetContent()method that returns the current content
Program.cs: Create anEditorclass that acts as the invoker. It should have aSetCommand(ICommand command)method and anExecuteCommand()method that runs the current command. In your main code, demonstrate the command pattern by processing a series of editing operations.
You will receive the following inputs:
- Number of commands to execute
- For each command: the command type (
insertordelete) followed by either the text to insert or the number of characters to delete
After executing all commands, print the final document content on a new line with the format Content: {content}.
For example, if the inputs are:
4
insert
Hello
insert
World
delete
3
insert
!The output should be:
Inserted: Hello
Inserted: World
Deleted: 3 characters
Inserted: !
Content: Hello Wo!Notice how the Editor (invoker) doesn't know anything about text manipulation - it simply executes whatever command it's given. The commands encapsulate both the action and the receiver, making it easy to add new operations like ReplaceCommand without changing the editor!
Cheat sheet
The Command pattern is a behavioral pattern that encapsulates a request as a stand-alone object containing all information about the request. This allows you to pass requests as method arguments, queue them, log them, or support undoable operations.
The pattern has four key components:
- Command interface - defines the Execute() method
- Concrete commands - implement the command interface and encapsulate specific actions
- Receiver - the object that performs the actual work
- Invoker - the object that triggers commands without knowing their implementation
Command Interface and Concrete Commands
public interface ICommand
{
void Execute();
}
public class TurnOnCommand : ICommand
{
private Light _light;
public TurnOnCommand(Light light) => _light = light;
public void Execute() => _light.TurnOn();
}
public class TurnOffCommand : ICommand
{
private Light _light;
public TurnOffCommand(Light light) => _light = light;
public void Execute() => _light.TurnOff();
}Receiver
public class Light
{
public void TurnOn() => Console.WriteLine("Light is ON");
public void TurnOff() => Console.WriteLine("Light is OFF");
}Invoker
public class RemoteControl
{
private ICommand _command;
public void SetCommand(ICommand command) => _command = command;
public void PressButton() => _command.Execute();
}Usage
var light = new Light();
var remote = new RemoteControl();
remote.SetCommand(new TurnOnCommand(light));
remote.PressButton(); // Light is ON
remote.SetCommand(new TurnOffCommand(light));
remote.PressButton(); // Light is OFFThe Command pattern is useful for implementing undo functionality, macro recording, or queuing operations for later execution. Each command encapsulates everything needed to perform an action, making systems more flexible and extensible.
Try it yourself
using System;
using TextEditor;
// TODO: Create the Editor class (the invoker)
public class Editor
{
// TODO: Add a private field to store the current command
private ICommand _command;
// TODO: Implement SetCommand method
public void SetCommand(ICommand command)
{
// TODO: Store the command
}
// TODO: Implement ExecuteCommand method
public void ExecuteCommand()
{
// TODO: Execute the current command
}
}
class Program
{
public static void Main(string[] args)
{
// Read number of commands
int n = Convert.ToInt32(Console.ReadLine());
// Create the document (receiver)
Document document = new Document();
// Create the editor (invoker)
Editor editor = new Editor();
// TODO: Process each command
for (int i = 0; i < n; i++)
{
string commandType = Console.ReadLine();
// TODO: Based on commandType, create the appropriate command
// - If "insert": read the text and create InsertCommand
// - If "delete": read the count and create DeleteCommand
// Then set the command on the editor and execute it
}
// TODO: Print the final content with format "Content: {content}"
}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesNamespaces & DirectivesIntro to Classes & ObjectsThe 'this' KeywordMethods and ParametersFields vs PropertiesConstructorsObject InitializersRecap - Simple Calculator4Inheritance
Basic Inheritance (:) SyntaxThe 'base' KeywordVirtual & Override KeywordsSealed ClassesThe 'object' Base ClassRecap - Employee Hierarchy7Advanced Features
Operator OverloadingIndexers (this[])ToString() OverrideExtension MethodsRecap - Custom List2Properties & Static Members
Auto-Implemented PropertiesRead/Write-Only PropertiesStatic Fields & MethodsStatic ClassesExpression-Bodied Members5Polymorphism & Interfaces
Compile vs Runtime PolyInterface vs Abstract ClassMultiple InterfacesExplicit InterfacesUpcasting & DowncastingRecap - Shape Calculator8Advanced OOP Concepts
Composition over InheritanceGenerics (Classes & Methods)Delegates and EventsAttributes and ReflectionIDisposable & using StatementDependency Injection Basics11Design Patterns Part 2
Command PatternAdapter PatternDecorator PatternTemplate Method PatternState PatternComposite Pattern