大多数 C# 命令模式实现或多或少与 Java 实现相同。这些实现通常使用 ICommand 接口:
public interface ICommand
{
void Execute();
}
然后强制所有命令类实现接口。我对这个解决方案没有任何问题,但我个人不喜欢创建太多的类,我更喜欢使用 .NET 委托(Java 中没有委托)。如果只需要一个方法引用,Action 委托通常可以解决问题:
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()
{
}
}
如果您的命令界面需要多个方法,例如:
public interface ICommand
{
void Execute();
void Undo();
}
您可以使用这样的包装类:
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; }
}
或(不管是哪一个)
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();
}
}
(如果您已经使用了遗留的东西,这个甚至可以实现 ICommand。如果您使用接口,工厂应该使用接口而不是 Command 类)
使用这样的包装器,您不必为要支持的每个操作创建命令类。以下示例演示了如何使用包装类:
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()
{
}
}
如您所见,即使您有多个方法(执行、撤消等),也无需实现接口。请注意,Execute 和 Undo 方法可能属于不同的类。您可以自由地以感觉更自然的方式构建代码,并且仍然可以使用命令模式。