18

我正在开发一个带有基本 UI 的 WinForm .Net 应用程序,其中包括启动相同底层代码的工具栏按钮、菜单项和击键。现在,每个事件处理程序调用一个通用方法来执行该功能。

根据我的阅读,这种类型的操作可以由命令设计模式处理,并具有自动启用/禁用或选中/取消选中 UI 元素的额外好处。

我一直在网上搜索一个好的示例项目,但真的没有找到。有没有人可以分享一个很好的例子?

4

5 回答 5

20

让我们首先确保我们知道命令模式是什么:

命令模式将请求封装为对象,并为其提供已知的公共接口。命令模式确保每个对象都接收自己的命令,并在发送者和接收者之间提供解耦。发送者是调用操作的对象,接收者是接收请求并对其进行操作的对象。

这是给你的一个例子。有很多方法可以做到这一点,但我将采用基于接口的方法来使代码更易于测试。我不确定您喜欢哪种语言,但我是用 C# 编写的。

首先,创建一个描述命令的接口。

public interface ICommand
{
    void Execute();
}

其次,创建将实现命令接口的命令对象。

public class CutCommand : ICommand
{
    public void Execute()
    {
        // Put code you like to execute when the CutCommand.Execute method is called.
    }
}

第三,我们需要设置我们的调用者或发送者对象。

public class TextOperations
{
    public void Invoke(ICommand command)
    {
        command.Execute();
    }
}

第四,创建将使用调用者/发送者对象的客户端对象。

public class Client
{
    static void Main()
    {
        TextOperations textOperations = new TextOperations();
        textOperation.Invoke(new CutCommand());
    }
}

我希望你能把这个例子应用到你正在开发的应用程序中。如果您想了解更多信息,请告诉我。

于 2008-08-18T20:51:49.070 回答
2

你在正确的轨道上。基本上,您将拥有一个代表文档的模型。您将在 CutCommand 中使用此模型。您将需要更改 CutCommand 的构造函数以接受您要剪切的信息。然后,每次单击 Cut 按钮时,您都会调用一个新的 CutCommand 并在构造函数中传递参数。然后在调用 Execute 方法时在类中使用这些参数。

于 2008-08-21T18:42:44.407 回答
1

尝试开源的 .NET 编辑器,例如SharpDevelopNotepad++

http://c2.com/cgi/wiki?CommandPattern上(自然)有一些关于命令模式的讨论,这可能会有所帮助。

于 2008-08-18T19:17:42.347 回答
1

Qt 对菜单栏/工具栏项目使用命令模式。

QActions 与 QMenuItem 和 QToolbar 分开创建,Actions 可以分别通过 setAction() 和 addAction() 方法分配给 QMenuItem 和 QToolbar。

http://web.archive.org/web/20100801023349/http://cartan.cas.suffolk.edu/oopdocbook/html/menus.html

http://web.archive.org/web/20100729211835/http://cartan.cas.suffolk.edu/oopdocbook/html/actions.html

于 2008-08-21T19:02:32.160 回答
0

我无法为您提供示例链接,但可以自己提供示例。

1)定义ICommand接口:

public interface ICommand {
   void Do();
   void Undo();
}

2)为具体命令执行 ICommand 实现,同时为它们定义抽象基类:

public abstract class WinFormCommand : ICommand {

}

3)创建命令调用程序:

public interface ICommandInvoker {
  void Invoke(ICommand command);
  void ReDo();
  void UnDo();
}

public interface ICommandDirector {
  void Enable(ICommand);
  void Disable(ICommand);
}

public class WinFormsCommandInvoker : ICommandInvoker, ICommandDirector {

    private readonly Dictionary<ICommand, bool> _commands;
    private readonly Queue<ICommand> _commandsQueue;       
    private readonly IButtonDirector _buttonDirector;

    // you can define additional queue for support of ReDo operation

    public WinFormsCommandInvoker(ICommandsBuilder builder, IButtonDirector buttonDirector) {
      _commands = builder.Build();
      _buttonDirector = buttonDirector;
      _commandsQueue = new Queue<ICommand>();
    } 

    public void Invoke(ICommand command) {
        command.Do();
        __commandsQueue.Enqueue(command);
    }

    public void ReDo() {
      //you can implement this using additional queue
    }

    public void UnDo() {
      var command = __commandsQueue.Dequeue();
      command.Undo();
    }

    public void Enable(ICommand command) {
      _commands.[command] = true;
      _buttonDirector.Enable(command);
    }

    public void Disable(ICommand command) {
      _commands.[command] = false;
      _buttonDirector.Disable(command); 
    }
}

4) 现在您可以实现您的 ICommandsBuilder、IButtonDirector 并将其他接口(例如 ICheckBoxDirector)添加到 WinFormsCommandInvoker。

于 2015-12-29T14:24:11.860 回答