Command Pattern
Command Pattern
Today’s post will explain what is the command pattern and how to
use it in C#.
You can read my previous posts about design patterns here:
Structural patterns
Decorator pattern
Proxy pattern
Facade pattern
Adapter pattern
Composite pattern
Bridge pattern
Flyweight pattern
Creational patterns
Singleton pattern
Abstract Factory pattern
Prototype pattern
Factory Method pattern
Builder pattern
Behavioral Patterns
Strategy pattern
Iterator pattern
Template method pattern
Command Pattern
The command pattern is a very useful pattern.
The main role of the pattern is to encapsulate a request in an
object. By encapsulating the request we gain the following support if
needed:
- Redo and Undo operations.
- Requests can be specify, queue and executed when needed.
- Logging requests can be handled.
- Composition of transactions inside an object that include the
transaction atomic operations.
The pattern is used a lot in .Net framework.
System.Data.SqlClient.SqlCommand is an example of the use of command
in ADO.NET. The SqlCommand encapsulate the internal issues of how to
do database operations and give a simple API to execute methods such as
ExecuteScalar, ExecuteNonQuery and etc. Every data access class that
uses the SqlCommand is the command invoker.
Use Cases for the Command Pattern
You should use the pattern in the following cases:
- You need support for logging of the changes performed by
commands. - You need redo or undo support.
- You have commands that different clients can handle in different
ways. - You have a set of atomic operations that you want to include in
a transaction.
UML Diagram
Example in C#
#region Command
interface Command
{
void Execute();
}
#endregion
#region Concrete Command
class ConcreteCommand : Command
{
#region Members
private readonly Receiver _receiver;
#endregion
#region Ctor
/// <summary>
/// Construct a new ConcreteCommand with the
/// given receiver
/// </summary>
/// <param name="receiver">The given receiver</param>
public ConcreteCommand(Receiver receiver)
{
_receiver = receiver;
}
#endregion
#region Command Members
void Command.Execute()
{
_receiver.Action();
}
#endregion
}
#endregion
#region Receiver
class Receiver
{
public void Action()
{
// write whatever action you need
}
}
#endregion
#region Invoker
class CommandInvoker
{
#region Members
private readonly Command _command;
#endregion
#region Ctor
/// <summary>
/// Construct a new Command Invoker with
/// the given command
/// </summary>
/// <param name="command">The given command</param>
public CommandInvoker(Command command)
{
_command = command;
}
#endregion
#region Methods
public void ExecuteCommand()
{
_command.Execute();
}
#endregion
}
#endregion
The example is very simple. I use a Command interface to hold
the command API that I need. The ConcreteCommand class
implement the interface and holds the receiver of the command
which implement the action of the command. The command itself
is invoked by the CommandInvoker class.
Redo and Undo Code Example
A request for an example of how to make a redo and undo operations
in the pattern was issued in the comment section. The following example
is a very simple example of how to make a redo and undo operations:
#region Command
interface Command
{
void Execute();
void Undo();
void Redo();
}
#endregion
#region Concrete Command
class ConcreteCommand : Command
{
#region Members
private readonly Receiver _receiver;
#endregion
#region Ctor
/// <summary>
/// Construct a new ConcreteCommand with the
/// given receiver
/// </summary>
/// <param name="receiver">The given receiver</param>
public ConcreteCommand(Receiver receiver)
{
_receiver = receiver;
}
#endregion
#region Command Members
void Command.Execute()
{
_receiver.Action();
}
public void Undo()
{
_receiver.UndoAction();
}
public void Redo()
{
_receiver.RedoAction();
}
#endregion
}
#endregion
#region Receiver
abstract class Receiver
{
#region Methods
public abstract void Action();
public abstract void UndoAction();
public abstract void RedoAction();
#endregion
}
#endregion
#region Concrete Receiver
class ConcreteReceiver : Receiver
{
#region Consts
private const int NUMBER_TO_ADD = 1;
#endregion
#region Members
private int _nCurrentState;
private int _nOldState;
#endregion
#region Methods
public override void Action()
{
// save the current state
_nOldState = _nCurrentState;
// do the action of string concat
_nCurrentState += NUMBER_TO_ADD;
Console.WriteLine("Current state {0}",
_nCurrentState);
}
public override void UndoAction()
{
// Return the old state to be the current state
_nCurrentState = _nOldState;
Console.WriteLine("Undo Current state back to {0}",
_nCurrentState);
}
public override void RedoAction()
{
// Redo calls the action again to redo
// the adtion
Action();
}
#endregion
The example is based on the code that was showed earlier in
the post. The only difference is that I added the redo and undo
operations and added a ConcreteReceiver that handles the redo and
undo operations. The example is simple and the undo operation only
saves the last action state. Also, the redo performs the action again
as indicated from a redo operation.
Summary
To sum up the post, I introduced the command pattern.
The pattern is widely used in the .Net framework and is very helpful
once you know how to use it. It can simplify the way you build requests
in the systems that you develop.
The next stop in the tour of behavioral patterns will be the chain
of responsibility pattern.