命令模式
使用命令模式,对于undo机制。
封装一个请求作为一个对象,让你参数化客户端,对于不同的请求,队列或者日志请求,并且支持可撤销操作。
这个模式最大的优势就是,它解耦了调用操作的对象,从一个如何知道它如何执行的对象。
开发一个简单的Notepad克隆。
第一步,我们想去创建一个抽象,围绕我们的textbox控件。在命令模式,这个抽象叫做接收者。
接收者在我们的例子中是一个对象,叫做Document。
class Document
{
private TextBox textbox;
public Document(TextBox textbox)
{
this.textbox = textbox;
}
public void BoldSelection()
{
Text = String.Format("<b>{0}<b>", Text);
}
public void UnderlineSelection()
{
Text = String.Format("<u>{0}</u>", Text);
}
public void ItalicizeSelection()
{
Text = String.Format("<i>{0}</i>", Text);
}
public void Cut()
{
textbox.Cut();
}
public void Copy()
{
textbox.Copy();
}
public void Paste()
{
textbox.Paste();
}
public string Text
{
get { return textbox.Text; }
set { textbox.Text = value; }
}
}
黑体选择,下划线选择,斜体(Italicize)选择。
我们已经定义于Document对象的,是一些操作,可以于document执行,完整地解耦这个功能从我么的应用。
如果我们想要改变加粗选定内容时所发生的情况,我们会转到这个对象,而不是转到表示代码。
第二步,我们将需要去设计我们的命令接口。自从可能,我们有一些命令不需要undo机制(例如,Copy),我们已经创建两个基类(Command和UndoableCommand)。我们将在本文的后面看一下UndoableCommand是如何连接的。目前,只要记住,这是一个类,去派生,如果你需要你的命令能够undo它自己。
public abstract class Command
{
public abstract void Execute();
}
public abstract class UndoableCommand : Command
{
public abstract void Undo();
}
为了处理粗体,我们将创建如下的代码:
class BoldCommand : UndoableCommand
{
private Document document;
private string previousText;
public BoldCommand(Document doc)
{
this.document = doc;
previousText = this.document.Text;
}
public override void Execute()
{
document.BoldSelection();
}
public override void Undo()
{
document.Text = previousText;
}
}
通过创建一个document对象,包裹文本盒子,我们能够完整地解耦对象,它将调用操作(一个菜单项)从一个如何知道执行(document object)解耦。
剩下的命令对象非常类似于上面。
剩下的代码,我们将需要去带来所有的事物在一起,是一个CommandManager。CommandManager是一个非常简单的类,
它有一个内部的栈,持续追踪我们的命令对于我们的undo机制。
class CommandManager
{
private Stack commandStack = new Stack();
public void ExecuteCommand(Command cmd)
{
cmd.Execute();
if (cmd is UndoableCommand)
{
commandStack.Push(cmd);
}
}
public void Undo()
{
if (commandStack.Count > 0)
{
UndoableCommand cmd = (UndoableCommand)commandStack.Pop();
cmd.Undo();
}
}
}
我们看上面的代码,我们只需要去添加命令到undo栈,如果它是一个UndoableCommand。