대부분의 C# 명령 패턴 구현 : 실행시
편집 귀하의 코멘트에 대한 답변에서
, 당신이 뭔가를 할 수 있습니다 만 인스턴스화 . 이러한 구현은 일반적으로 ICommand 인터페이스를 사용합니다.
public interface ICommand
{
void Execute();
}
그런 다음 모든 명령 클래스가 강제로 인터페이스를 구현합니다. 이 솔루션에는 문제가 없지만 개인적으로 너무 많은 클래스를 만드는 것을 좋아하지 않으며 대신 .NET 대리자를 사용하는 것을 선호합니다 (Java에서는 대리자가 없습니다). 액션 위임은 보통 하나의 방법 참조를 필요로하는 경우 트릭을 수행합니다
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 메서드는 다른 클래스에 속할 수 있습니다. 더 자연스럽고 여전히 명령 패턴을 사용할 수있는 방식으로 코드를 자유롭게 구조 할 수 있습니다.
이것은 귀하의 모든 명령이 귀하의 공장에 있어야한다는 것을 고려할 때 결함이있는 것으로 보입니다. – KingOfHypocrites