Welcome to SpellCoder Sign in | Join | Help

Command Design Pattern in C# 2.0

I have posted before about how to implement the observer pattern using C# in a way that is more suitable to C# and uses its functionalities to produce more elegant code.
This time I am re-implementing the Command pattern in a C# way.
First of all, let's see the classic Command Pattern UML diagram

As you can see the pattern consists of five actors
  1. Invoker
  2. Command (interface)
  3. Concrete Command class(es)
  4. Receiver
  5. Client
for more information about Command pattern check here
Now let's see how it can look like in C# world.

Let's see how the Command interface will look like
delegate void CommandHandle<T>(T receiver);
Awesome doesn't it, just one line :)

Let's see the Command Concrete Class
sealed class Command<T>
{
T _receiver;

CommandHandle<T> _doCommand;
CommandHandle<T> _undoCommand;

public Command(CommandHandle<T> doCommand, T receiver)
{
_doCommand = doCommand;
_receiver = receiver;
}

public Command(CommandHandle<T> doCommand, CommandHandle<T> undoCommand, T receiver)
: this(doCommand, receiver)
{
_undoCommand = undoCommand;
}

public void Execute()
{
if(_doCommand != null)
_doCommand(_receiver);
}

public void Undo()
{
if(_undoCommand != null)
_undoCommand(_receiver);
}
}

This is a generic class so it can be used for most cases instead of creating multiple inherited classes, the class has two references of the CommandHandler delegate one for the DoCommand and the other is for the UndoCommand

Let's see how the Receiver class will look like,
class Receiver
{
private int _state;

public int State
{
get { return _state; }
set { _state = value; }
}
}
Actually it doesn't matter how it looks like, so the previous code is just a sample class.

Let's now see how the Invoker class will look like
class Invoker
{
List<Command<Receiver>> _commands;

public Invoker()
{
_commands = new List<Command<Receiver>>();
}

public void AddCommand(Command<Receiver> command)
{
_commands.Add(command);
}

public void RemoveCommand(Command<Receiver> command)
{
_commands.Remove(command);
}

public void CallCommands()
{
foreach (Command<Receiver> command in _commands)
{
command.Execute();
}
}

public void UndoCommands()
{
foreach (Command<Receiver> command in _commands)
{
command.Undo();
}
}
}

The invoker is just a class that is interested in the Receiver objects and want to apply certain actions on instance(s) of the Receiver class, so it uses a list of Command<Receiver> to encapsulate the executing code.

Finally, we should see how the Client will use these classes.
class Program
{
static void Main(string[] args)
{
Receiver recv1 = new Receiver();
Receiver recv2 = new Receiver();
Command<Receiver> command1 = new Command<Receiver>(new CommandHandle<Receiver>(Func1), new CommandHandle<Receiver>(UndoFunc1), recv1);
Command<Receiver> command2 = new Command<Receiver>(new CommandHandle<Receiver>(Func2), recv2);
Invoker invoker = new Invoker();
invoker.AddCommand(command1);
invoker.AddCommand(command2);
invoker.CallCommands();
invoker.UndoCommands();

}

static void Func1(Receiver recv1)
{
recv1.State ++;
Console.WriteLine(recv1.State);
}

static void Func2(Receiver recv2)
{
recv2.State+=2;
}

static void UndoFunc1(Receiver recv)
{
recv.State--;
Console.WriteLine(recv.State);
}
}
So the main difference between the classic implementation and this one, that
  1. We didn't define an interface and we juts used a generic delegate
  2. We don't need to inherit from the interface every time we want to use the command pattern for different Receiver type, we replaced this with a generic Command class.
I hope you like it, I attached the previous code with the post
Have fun
kick it on DotNetKicks.com
Published Sunday, March 25, 2007 9:08 PM by Mohammed Hossam
Filed Under: , ,
Attachment(s): CommandPattern.zip

Comments

# re: Command Design Pattern in C# 2.0

Monday, March 26, 2007 6:13 AM by Chris Davis
Hi, since you are using Generic's would it not be faster to use the generic list's .foreach method:

_commands.foreach(delegate(Command<Receiver> command) {
command.Execute();
});

# re: Command Design Pattern in C# 2.0

Monday, March 26, 2007 6:25 AM by tayseer
In the invoker: you should undo a single command, not all commands.

You should add an index for all the 'Design Patterns' posts.

# re: Command Design Pattern in C# 2.0

Monday, March 26, 2007 7:37 AM by Mohammed Hossam
@Tayseer
You can edit the code easily to select which command to undo.
A created a new Design Patterns category in the blogs, thanks for the hint

# re: Command Design Pattern in C# 2.0

Tuesday, March 27, 2007 12:52 PM by foobar
Excellent post.
Anonymous comments are disabled