一、什么是备忘录模式?
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原先保存的状态。
比如像我们平常使用的Ctrl+Z撤销操作、浏览器里面的回退操作、还有数据库的事务回滚、手机相册删除的照片可以恢复,这些都是让你吃“后悔药”的行为。体现了备忘录模式。
Originator(发起人):负责创建一个备忘录Memento,用以记录当前时刻它的内部状态,并可使用备忘录恢复内部状态。Originator可根据需要决定Memento存储Originator的那些内部状态。
Memento(备忘录):负责存储Originator对象的内部状态。
Caretaker(管理者):负责保存好备忘录Memento,不能对备忘录的内容进行操作或检查。
二、备忘录模式有什么优点吗?
把要保存的细节给封装在了备忘录中了,哪一天要更改保存的细节也不用影响客户端了。
实现了恢复机制
三、有什么缺点吗?
消耗资源。发起人的状态需要完整存储到备忘录对象中,如果状态数据很大很多,那么在资源消耗上,备忘录对象会非常耗内存。
四、什么场合使用备忘录模式?
适用于功能比较复杂的,但需要维护或记录属性历史的类,或者需要保存的属性只是众多属性中的一小部分时,Originator可以根据保存的Memento信息还原到前一状态。
如果再某个系统中使用命令模式时,需要实现命令的撤销功能,那么命令模式可以使用备忘录模式来存储可撤销操作的状态。
使用备忘录可以把负责的对象内部信息对其他的对象屏蔽起来。
当角色的状态改变的时候,有可能这个状态无效,这时候就可以使用暂时存储起来的备忘录将状态复原。
五、代码展示
场景:游戏的某个场景,一游戏角色有生命力、攻击力、防御力等等数据,在打Boss前和后一定会不一样的,我们允许玩家如果感觉与Boss决斗的效果不理想可以让游戏回复到决斗前。
①、备忘录模式
发起人(Originator)类
class Originator { private string state; //成员变量 public string State //需要保存的属性 { get { return state; } set { state = value; } } //创建备忘录 public Memento CreateMemento() { //讲当前需要保存的信息导入并实例化出一个Memento对象 return (new Memento(state)); } //恢复备忘录 public void SetMemento(Memento memento) { state = memento.State; //将Memento导入并将相关数据恢复 } //显示数据 public void Show() { Console.WriteLine("State={0}", state); } }
备忘录(Memento)类
class Memento { private string state; //成员变量,状态 public Memento(string state) //有参构造方法 { this.state = state; } public string State //需要保存的数据属性,可以是多个 { get { return state; } //只能保存数据,防止外界修改 } }
管理类(Caretaker)类
class Caretaker { private Memento memento; public Memento Memento //得到或设置备忘录 { get { return memento; } set { memento = value; } } }
客户端
Originator o = new Originator(); //实例化一个发起人 o.State = "On"; //初始状态属性为“On” o.Show(); //显示当前状态 Caretaker c = new Caretaker(); //创建一个管理者 //发起人创建一个备忘录,将创建的备忘录复制给管理者的属性 c.Memento = o.CreateMemento(); o.State = "Off"; //状态属性为“Off” o.Show(); //显示当前状态 o.SetMemento(c.Memento); //管理者调用保存的数据赋值给发起人并恢复备忘录 o.Show(); //显示当前状态 Console.ReadKey();