首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

【2013.2.19】医生,请给小弟我三份后悔药,小弟我要打包带走。——Memento

2013-02-24 
【2013.2.19】医生,请给我三份后悔药,我要打包带走。——Memento// // // // // // // // /////2013.2.19// //

【2013.2.19】医生,请给我三份后悔药,我要打包带走。——Memento

// // // // // // // // //

///2013.2.19

// // // // // // // // //

"曾经有一份真挚的爱情摆在我面前,

我没有去珍惜,

等到失去了才追悔莫及。

如果上天能再给我一次机会,

我一定要说出那三个字——我要当导演。"


时光如梭。

还记得当年那个踢过少林足球,点过秋香,当过喜剧之王的至尊宝,

如今已俨然变身成了胡茬大叔,

做起了导演。


时光如梭。

当年,现在。


也许你一定还有一件事情,

至今后悔当初没那样做。


很可惜,

我们没有月光宝盒。

很幸运,

因为我们有Memento(模式),

可以让我们重头来过。


当然,

这个模式的具体应用更是众所周知——"Undo"。

中文里我们管它叫做"撤销"。


【核心】返回过去的存在状态。


UML图:

【2013.2.19】医生,请给小弟我三份后悔药,小弟我要打包带走。——Memento


这个存在于众多软件之中的功能,

更多时候我们只是简单地按下Ctrl+Z来执行。


但是,

有问题。


大家想过没有,

撤销,这项功能,

该存在于代码结构的什么位置呢?


存在于撤销所在的本体类?

不行,

因为假设我们将本体进行了修改,

按下撤销时,

本体连同撤销一起返回了过去的状态。

(关于这个问题就好像大炮对准自己发射,将炮本身炸坏了然后仍要发射炮弹一样……请原谅笔者无力的解释^_^|||)


存在与外部类?

也不好,

因为毕竟是自己的状态,

怎么能公开呢?

但如果外部类不公开,

自己又怎么将状态传过去呢?

(关于这个问题就好像要将一枚硬币放进封口的瓶子里一样……请再次原谅笔者无力的解释T_T)


等等,

第二个问题我们是不是可以简化成下面这句话?

想办法访问外部类的私有数据。


对了,

我猜你已经想到了。

在C++中,

解决这个问题的关键就是——

友元类。


示例代码:


【大致思路】

Originator是一个系统,状态使用state(string类型)来储存。

Memento是其友元类,用于存储Originator旧状态。


Memento.h



注意事项:


其实代码本身并没有太多可以讲解的,

毕竟注释已经写得很清楚了。


不过关于撤销还是有点话想说的。

不知道大家有木有注意到过,

撤销也是分为不同类别的。


最常见的是notepad(记事本)的撤销,

如果连续按下去的话,

它只是在当前命令与上一命令之间来回切换而已。

就像这样:A->B->A->B->A->.....


这一类的实现是很容易的,

笔者的撤销就属于这一类。


另一类的撤销就稍微复杂点了,

比如说各个编译器(VS,MonoDeveloper等)的撤销命令,

按下去Ctrl+Z就是一直返回过去的状态,

就像这样:E->D->C->B->A->....

但是相对的,

它也具有"重做"命令(一般是Ctrl+Y),

其与撤销是反操作的,

就像这样:A->B->C->D->E


这一类的撤销的实现稍微复杂点,

涉及到了堆栈的使用。

但每个软件的设计不同,

因此也不能一概而论。


除此之外,

还有一类撤销,

可以随时返回过去任意状态,

最明显的例子就是PS的历史记录了,

点到哪里就返回哪里。

这类撤销的设计方式类似于List或是Hash table.


顺便说一句,

PS具有多种撤销方式,

因为除了历史记录之外它也可以Ctrl+Z。


其实除了PS,

大多数艺术类软件都是同样的设计方式,

例如3ds Max,Mudbox,或是Illustrator,

因为这样非常方便进行艺术创作(想一想为什么)。



说一点题外话吧,

——

其实有时候真想在自己肚子上安装一个撤销按钮,

一按下去,

扑哧,就返回过去了。


#Problems

但这种想法是很超前的,

因为现实世界这个系统太过于庞大,

目前还没有一个处理器能处理万物的行为,

还有没有一个硬盘可以存储万物的状态,

更没有一个强大的系统可以完全模拟这一切。


尽管如此,

有时候笔者也会站在洒满阳光的窗台前,

望着灿烂了整个暮空的夕阳,

思考这种系统的设计方式。


目前最初级的想法是创建一个4纬位数组,

三个轴存储空间位运算,

最后一个存储时间的位运算,

然后每隔一段时间将现有数组与原数组进行对比,

发生改变的部分push到一个状态栈中去,

然后当按下肚子上的撤销按钮时,

就从此状态栈中pop一个状态出来,

将自己现有状态替换掉。


但是实现起来有困难,

困难是什么呢?

goto #Problems;


郭德纲都上春晚了,

笔者这个单纯的想法还没能实现,


不得不说这是人生一大憾事。


所以,

在发明出这种系统(机器?)之前,

还是珍惜当下吧。


不要让自己有任何遗憾,

这样就不会想穿梭时光了。

热点排行