Dve*_*Dve 7 c# delegates design-patterns command-pattern
是否可以使用Queue of Action代理实现GOF命令模式?
我一直试图绕过它一段时间而且我很难过,因为我想要添加到队列中的每个可能的动作可能有不同数量的参数.
有什么建议?我是否通过专注于命令模式来咆哮错误的树?
更新:
非常感谢jgauffin,这是一种享受...我的实现现在看起来像
public class CommandDispatcher
{
private readonly Dictionary<Type, List<Action<ICommand>>> _registeredCommands =
new Dictionary<Type, List<Action<ICommand>>>();
public void RegisterCommand<T>(Action<ICommand> action) where T : ICommand
{
if (_registeredCommands.ContainsKey(typeof (T)))
_registeredCommands[typeof (T)].Add(action);
else
_registeredCommands.Add(typeof (T), new List<Action<ICommand>> {action});
}
public void Trigger<T>(T command) where T : ICommand
{
if (!_registeredCommands.ContainsKey(typeof(T)))
throw new InvalidOperationException("There are no subscribers for that command");
foreach (var registeredCommand in _registeredCommands[typeof(T)])
{
registeredCommand(command);
if (command.Cancel) break;
}
}
}
Run Code Online (Sandbox Code Playgroud)
jga*_*fin 10
您可以使用Action.您不应该使用多个参数.如果命令需要新参数会发生什么?然后,您需要更改调用该命令的所有位置以及处理程序.
相反,您应该使用具有所有参数作为属性的Command类.通过这种方式,您可以添加参数而不会影响代码(新参数应在处理程序中视为可选参数).
我就是这样做的:
public interface ICommand
{
// Cancel processing, do not invoke any more handlers
public bool Cancel { get; set; }
}
public class CommandDispatcher
{
private Dictionary<Type, List<Action<ICommand>>> _commands = new Dictionary<Type, List<Action<ICommand>>>();
// Add to dictionary here
public void Subscribe<T>(Action<T> action) where T : ICommand
{
List<Action<ICommand>> subscribers;
if (!_commands.TryGetValue(typeof(T), out subscribers))
{
subscribers = new List<Action<ICommand>>();
_commands.Add(typeof(T), subscribers));
}
subscribers.Add(action);
}
// find command and to foreach to execute the actions
public void Trigger<T>(T command) where T : ICommand
{
List<Action<ICommand>> subscribers;
if (!_commands.TryGetValue(typeof(T), out subscribers))
throw new InvalidOperationException("There are no subscribers for that command");
foreach(var subsriber in subscribers)
{
subscriber(command);
if (command.Cancel)
break; //a handler canceled the command to prevent others from processing it.
}
}
}
public class AddTextCommand : ICommand
{
public string TextToAdd {get;set;}
}
public class TextHandler
{
public TextHandler(CommandDispatcher dispatcher)
{
disptacher.Subscribe<AddTextCommand>(OnAddText);
}
public void OnAddText(AddTextCommand cmd)
{
//....
}
}
public partial class MyForm : Form
{
CommandDispatcher _dispatcher;
private void MyTextBox_Changed(object source, EventArgs e)
{
_dispatcher.Trigger(new AddTextCommand{TextToAdd = MyTextBox.Text}=;
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,代码是一种伪代码.我在没有测试的情况下直接在答案中写了它.您可能需要更改内容以使其正常工作,但它至少应该给您一个提示.实现允许您为每个命令添加多个订户.