是否可以使用动作委托队列来实现 GOF 命令模式?
一段时间以来,我一直在尝试解决这个问题,但我很困惑,因为我想要添加到队列中的每个可能的操作可能都有不同数量的参数。
有什么建议么?我是否因为专注于命令模式而找错了方向?
UPDATE:
非常感谢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;
}
}
}
您可以使用操作。您不应该使用多个参数。如果命令需要新参数会发生什么?然后,您需要更改调用命令和处理程序的所有位置。
相反,您应该使用将所有参数作为属性的 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}=;
}
}
请注意,该代码是一种伪代码。我没有测试就直接写在答案里了。您可能必须更改一些内容才能使其正常工作,但它至少应该给您一个提示。该实现允许您为每个命令添加多个订阅者。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)