[设计模式]Memento pattern(备忘录模式)在Paint.net中的应用
2007-11-16 22:26 水随风 阅读(556) 评论(0) 编辑 收藏 举报
========Paint.Net====waterlion=======Memento pattern(备忘录模式)====设计模式======
Paint.net是一个开源的图像编辑软件,是由美国一所大学的学生所开发。在里面我们可以学到很多的知识,比如画图啊!设计模式啊!等等。看到paint.net同时也看到了.net的强大,那么多功能paint.net总共也只有几M而已,所有的操作都被封装。自己也按耐不住相试试模仿一下里面的功能。
当我想做一个Undo(撤销)的时候,我从中体验到了设计模式的应用在处理问题上的优点,Undo操作是将原先对画板的操作取消。那么我们来看看paint.net是如何体现这种模式的
首先说明Undo的一个过程,因为有很多画笔,很多效果,那么把这些效果或者是图片的形成条件放在一个类中,这些类的结构为:
由HistoryMemento这个抽象类派生了很多的子类,这些子类就是根据不同的画笔或者效果而产生,目的就在于记录下产生这些画笔和效果的必要条件。
此下为HistoryMemento的部分代码
{
private string name;
public string Name
{
get
{
return this.name;
}
set
{
this.name = value;
}
}
private ImageResource image;
public ImageResource Image
{
get
{
return this.image;
}
set
{
this.image = value;
}
}
protected int id;
private static int nextId = 0;
public int ID
{
get
{
return this.id;
}
set
{
this.id = value;
}
}
//.
public HistoryMemento(string name, ImageResource image)
{
this.name = name;
this.image = image;
this.id = Interlocked.Increment(ref nextId);
}
又可见ToolHistoryMemento的记录类,该类继承于HistoryMemento
: HistoryMemento
{
private DocumentWorkspace documentWorkspace;
private Type toolType;
protected DocumentWorkspace DocumentWorkspace
{
get
{
return this.documentWorkspace;
}
}
public Type ToolType
{
get
{
return this.toolType;
}
}
protected abstract HistoryMemento OnToolUndo();
protected sealed override HistoryMemento OnUndo()
{
if (this.documentWorkspace.GetToolType() != this.toolType)
{
this.documentWorkspace.SetToolFromType(this.toolType);
}
return OnToolUndo();
}
public ToolHistoryMemento(DocumentWorkspace documentWorkspace, string name, ImageResource image)
: base(name, image)
{
this.documentWorkspace = documentWorkspace;
this.toolType = documentWorkspace.GetToolType();
}
}
监视备忘类,此类为保存状态及封装数据结构所用
{
private List<HistoryMemento> undoStack;
private List<HistoryMemento> redoStack;
//被省略代码
private HistoryStack(
List<HistoryMemento> undoStack,
List<HistoryMemento> redoStack)
{
this.undoStack = new List<HistoryMemento>(undoStack);
this.redoStack = new List<HistoryMemento>(redoStack);
}
//被省略代码
}
}
回到正题,为什么我们要抽象此类并为之改善条件,我们的目的在哪?我们为了什么?我们为了让在画板上处理图片的操作过程中更好的完成Memento Pattern(备忘者模式)所带来的快乐,因为我的操作被上述不同的类保存下来了。
好的,我们保存了这些类,也就是说我们应该已经完成了对画笔或者效果的记录。因为我们在画图的时候,如果需要改动某一项,我们会根据这些项进行重绘(这个我还没在paint.net看到相应的代码),重绘后的效果就是Undo后的效果
那么在Undo的时候,我们不能随意的去做这些操作,因为我们要按一定的顺序来做。Paint.net的方法就是虚拟一个HistoryStack(操作历史栈),因为我们的许多操作都被这样定义
private List<HistoryMemento> undoStack;
从这里可以看出对于我们的操作都保存在List的集合中,这样原子化的好处就是每一个操作都是透明的。栈的结构就不在这赘述了。我们可以简化一下图来看
Memento Pattern(备忘者模式)是如何工作的:
当然在HistoryStack不只是有Undo还有Redo原理一样都是用Stack来存储顺序,用List来存储操作集合。
==========================================================
第一次写关于设计模式的文章。如有错误,还请大家毫无保留的提出!!!