我有一个像Visual Studio设计器一样工作的窗口。每个文档都有两个视图:
我有一个可以发出不同命令的工具栏。工具栏按钮具有CommandId字符串属性,用于存储命令的Id,例如:
我无法设计命令模式,其中命令的执行因视图而异。
对于一个明显的示例,复制命令将在源视图中复制所选文本,但在 Designer视图中时将复制所选控件
我目前正在将 commandId 字符串映射到 CopyCommand 对象,但由于该命令的执行因视图而异,我不知道这应该如何实施。
每个视图是否应提供其理解的具体命令列表(因此有两个 CopyCommand ,如 SourceCopyCommand 和 DesignCopyCommand 分享相同的ID)?
或者每个命令都应该是唯一的,但是视图有一个很大的映射函数,可以根据命令ID改变行为吗?
答案 0 :(得分:2)
使用Strategy Pattern和State 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):
将请求封装为对象, 从而让你参数化 具有不同请求的客户端,队列 或记录请求,并支持可撤消 操作