当初学备忘录模式的时候,特别开心。这不就是游戏里的备份嘛!游戏关闭之后,重新开启,从上次结束的位置继续开始。但终归没有进入游戏行业,也没有机会用过备忘录模式。
UML类图位置:https://www.processon.com/view/link/60d29bf3e401fd49502afd25
本文代码链接为:https://github.com/shidawuhen/asap/blob/master/controller/design/25Memento.go
1.定义
1.1 备忘录模式
备忘录模式:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
UML:
1.2分析
从定义上看,除了不破坏封装性外,其它都比较容易理解。对于不破坏封装性,我觉得有两点:
- 备忘录是Originator自己创建的
- 备忘录应该只有获取相关的接口,不应该有修改相关的接口
Caretaker是做什么用的呢?备忘录不是只备忘一份,可能备忘多份,Caretaker就是管理众多备忘录的。
Originator通过CreateMemento创建备忘录,通过SetMemento恢复到指定状态。
为什么备份的时候使用的是Memento而不是直接使用Originator呢?这是因为Memento只保存数据,如果将Originator保存,则表示将功能也进行保存,属于不该保存的而保存了。
另外只保存数据还有一个好处,即使解析出数据,也不知道如何使用,只有Originator知道真正的口诀。
2.应用场景
游戏或者文档,经常使用到备份相关的功能。玩游戏打Boss的时候,一般会做存档,失败了重新来。文档也有回滚功能,否则毕业论文写着写着断电了,所有内容化为乌有,多惨。
以前写过Go设计模式(22)-状态模式,这也算一个简单的小游戏,正好用它为基础实现一个备忘录模式。
3.代码实现
1 | package main |
输出:
➜ myproject go run main.go
小马里奥
——————-获得蘑菇
超级马里奥
——————-获得斗篷
——————-备份一下,要打怪了,当前状态为
斗篷马里奥
当前分数为: 300
——————-开始打怪
斗篷马里奥
——————-遇到怪兽
——————-打怪失败,目前状态为
小马里奥
当前分数为: 100
——————-恢复状态,重新打怪
斗篷马里奥
当前分数为: 300
总结
简单写了一个小功能,还是挺麻烦的,我想这也是大家不太想用设计模式的一个原因。但是当使用的时候,却发现这个设计模式能够方便的实现很多功能,这也是有人想用设计模式的原因。
备忘录模式虽然不常用,但是对合适的场景还是很有帮助的。