ほとんどのC#のコマンドパターンの実装:実行するとき
EDITあなたのコメントに答えて
、あなたのような何かができる、唯一のインスタンス化します。これらの実装は、通常、ICommandインターフェイスを使用します:
public interface ICommand
{
void Execute();
}
そして、すべてのコマンドクラスが強制的にインターフェイスを実装します。私はこのソリューションに問題はありませんが、個人的にはあまりにも多くのクラスを作成するのが好きではなく、代わりに.NETデリゲートを使用する方が好みです(Javaではデリゲートはありません)。アクションデリゲートは、通常、1つの方法だけの参照が必要な場合は、トリックを行います。
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; }
}
か(それは問題ではない1)
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();
}
}
(これはすでにICEMandを実装しているかもしれません。インターフェイスを使用する場合、ファクトリは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メソッドは異なるクラスに属することがあることに注意してください。より自然な感じでコードを構造化することは自由ですが、依然としてコマンドパターンを使用することができます。
これはあなたのコマンドのすべてがあなたの工場になければならないことを考慮すると、間違っているようです。 – KingOfHypocrites