您的位置:首页 > 大数据 > 人工智能

[设计模式]Memento pattern(备忘录模式)在Paint.net中的应用

2007-11-16 22:26 513 查看
========Paint.Net====waterlion=======Memento pattern(备忘录模式)====设计模式======

Paint.net是一个开源的图像编辑软件,是由美国一所大学的学生所开发。在里面我们可以学到很多的知识,比如画图啊!设计模式啊!等等。看到paint.net同时也看到了.net的强大,那么多功能paint.net总共也只有几M而已,所有的操作都被封装。自己也按耐不住相试试模仿一下里面的功能。

当我想做一个Undo(撤销)的时候,我从中体验到了设计模式的应用在处理问题上的优点,Undo操作是将原先对画板的操作取消。那么我们来看看paint.net是如何体现这种模式的

首先说明Undo的一个过程,因为有很多画笔,很多效果,那么把这些效果或者是图片的形成条件放在一个类中,这些类的结构为:



由HistoryMemento这个抽象类派生了很多的子类,这些子类就是根据不同的画笔或者效果而产生,目的就在于记录下产生这些画笔和效果的必要条件。

此下为HistoryMemento的部分代码

public abstract class 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

public abstract class ToolHistoryMemento

: 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();

}

}

监视备忘类,此类为保存状态及封装数据结构所用

public class HistoryStack

{

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来存储操作集合。

==========================================================

第一次写关于设计模式的文章。如有错误,还请大家毫无保留的提出!!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: