如何使用不同的侦听器设计命令模式?

时间:2009-11-17 21:05:19

标签: c# design-patterns

我有一个像Visual Studio设计器一样工作的窗口。每个文档都有两个视图:

  • 来源视图,
  • 设计师视图。

我有一个可以发出不同命令的工具栏。工具栏按钮具有CommandId字符串属性,用于存储命令的Id,例如:

  • 剪切,复制,粘贴;
  • 插入网格,
  • 自动格式化
  • ...

我无法设计命令模式,其中命令的执行因视图而异。

对于一个明显的示例,复制命令将在源视图中复制所选文本,但在 Designer视图中时将复制所选控件

我目前正在将 commandId 字符串映射到 CopyCommand 对象,但由于该命令的执行因视图而异,我不知道这应该如何实施。

  • 每个视图是否应提供其理解的具体命令列表(因此有两个 CopyCommand ,如 SourceCopyCommand DesignCopyCommand 分享相同的ID)?

  • 或者每个命令都应该是唯一的,但是视图有一个很大的映射函数,可以根据命令ID改变行为吗?

2 个答案:

答案 0 :(得分:2)

使用Strategy PatternState Pattern的组合。使每个窗口实现一个接口,定义可以发送给它的常用命令 - 例如。 IWindowEditCommands。对于多平台窗口,使用内部策略对象为每个可能的窗口状态封装常用命令的不同实现。当您在窗口状态之间切换时,状态模式会进入 - 例如。设计视图和源视图。当窗口改变状态时,它会相应地更改commandState中存储的对象的类型,确保使用正确的具体策略来实现剪切,复制和粘贴。

要将其连接到菜单Command对象,只需让菜单命令找到当前选定的窗口并向其发送相应的消息。

public interface IWindowEditCommands
{
    string Copy();
    string Cut();
    void   Paste(string buffer);
}

public class Editor implements IWindowEditCommands
{
    private IWindowEditCommands commandState;

    //constructor and other methods

    public void SwitchToSourceView()
    {
        //do stuff
        commandState = new EditorSourceViewStrategy(this);
    }

    public void SwitchToDesignView()
    {
        //do stuff
        commandState = new EditorDesignViewStrategy(this);
    }

    //IWindowEditCommands methods
    public string Copy() { return commandState.Copy(); }
    public string Cut()  { return commandState.Cut(); }

    public void Paste(string buffer) { commandState.paste(buffer); }

}

public class EditorSourceViewStrategy implements IWindowEditCommands
{
    private Editor editor;

    public EditorSourceViewEditCommands(Editor editor)
    {
        this.editor = editor;
    }

    public string Copy() {return...} //return the selected source from the source view
    public string Cut()  {return...} //return the and delete the selected source from the source view
    public void Paste(String buffer) {} //insert the buffer text at the insertion point
}

public class EditorDesignViewStrategy implements IWindowEditCommands
{
    private Editor editor;

    public EditorDesignViewEditCommands(Editor editor)
    {
        this.editor = editor;
    }

    public string Copy() {return...} //return the selected TAGS from the source view
    public string Cut()  {return...} //return the and delete the selected TAGS from the source view
    public void Paste(String buffer) {} //insert the buffer text at the insertion point
}

答案 1 :(得分:0)

如果在ICommandContext中传递(如接收器,请参见“设计模式”第23页)。您的每个视图都将实现此接口,然后了解如何执行命令。 Command对象的唯一责任就是封装动作,这样你就可以从菜单中调用CopyCommand,从键盘“Ctrl + C”,右击复制,也许还有其他方式...

public interface ICommandContext 
{
void Cut();
void Copy();
void Past();
void AutoFormat(); 
}

public SourceView : ICommandContext
{
    public void Cut()
    {
        // Do stuff here...
    }
}

public class CopyCommand : Command
{
    public override Execute(ICommandContext context)
    {
        context.Copy();
    }
}

定义(来自dofactory):

  

将请求封装为对象,   从而让你参数化   具有不同请求的客户端,队列   或记录请求,并支持可撤消   操作