Most C# command pattern implementations more or less the same as a Java implementation. These implementations usually use a ICommand interface:
public interface ICommand
{
void Execute();
}
and then all command classes are forced to implement the interface. I have no issues with this solution, but personally I don't like creating too many classes and I prefer to use .NET delegates instead (there are no delegates in Java). The Action delegate usually does the trick if only need one method reference:
public class Prog
{
public Prog()
{
var factory = new CommandFactory();
factory.Register("A", () => new A().DoA);
factory.Register("B", () => new B().DoB);
factory.Register("C", DoStuff);
factory.Execute("A");
}
public static void DoStuff()
{
}
}
public class CommandFactory
{
private readonly IDictionary<string, Action> _commands;
public void Register(string commandName, Action action)
{
_commands.Add(commandName, action);
}
public Action GetCommand(string commandName)
{
_commands[commandName];
}
public void Execute(string commandName)
{
GetCommand(commandName)();
}
}
public class A
{
public void DoA()
{
}
}
public class B
{
public void DoB()
{
}
}
If your command interface needs more than one methods like:
public interface ICommand
{
void Execute();
void Undo();
}
You can use a wrapper class like this:
public class Command
{
public Command(Action execute, Action undo)
{
Execute = execute;
Undo = undo;
}
public Action Execute { get; protected set; }
public Action Undo { get; protected set; }
}
or (it doesn't matter which one)
public class Command
{
private readonly Action _execute;
private readonly Action _undo;
public Command(Action execute, Action undo)
{
_execute = execute;
_undo = undo;
}
public void Execute()
{
_execute();
}
public void Undo()
{
_undo();
}
}
(this one may even implement ICommand if you have legacy stuff using it already. If you use the interface the factory should use the interface instead of the Command class)
With a wrapper like this you are not forced to create a command class for each action you want to support. The following example demonstrates how you can use the wrapper class:
public class Prog2
{
public Prog2()
{
var factory = new CommandFactory2();
factory.Register("A", new Lazy<Command>(
()=>
{
var a = new A();
return new Command(a.DoA, a.UndoA);
}));
factory.Register("B", new Lazy<Command>(
() =>
{
var c = new B();
return new Command(c.DoB, c.DoB);
}));
factory.Register("C", new Lazy<Command>(
() => new Command(DoStuff, UndoStuff)));
factory.Execute("A");
}
public static void DoStuff()
{
}
public static void UndoStuff()
{
}
}
public class CommandFactory2
{
private readonly IDictionary<string, Lazy<Command>> _commands;
public void Register(string commandName, Lazy<Command> lazyCommand)
{
_commands.Add(commandName, lazyCommand);
}
public void Register(string commandName, Action execute, Action undo)
{
_commands.Add(commandName, new Lazy<Command>(() => new Command(execute, undo)));
}
public Command GetCommand(string commandName)
{
return _commands[commandName].Value;
}
public void Execute(string commandName)
{
GetCommand(commandName).Execute();
}
public void Undo(string commandName)
{
GetCommand(commandName).Undo();
}
}
public class A
{
public void DoA()
{
}
public void UndoA()
{
}
}
public class B
{
public void DoB()
{
}
public void UndoB()
{
}
}
As you can see there is no need to implement the interface even if you have more than one method (Execute, Undo, etc). Please note that the Execute and Undo methods may belong to different classes. You are free to structure your code the way it feels more natural and still can use the command pattern.