在不破坏封装的前提下,捕获并且保存一个对象的内部状态,这样可以将对象恢复到原先保存的状态。
类与对象的关系
备忘录(Memento)
l 保持原发器(Originator)的内部状态,根据原发器来据顶保存那些内部的状态
l
保护原发器(Originator)之处的对象访问备忘录。备忘录可以有效的利用两个接口。看管者(Caretaker)只能调用狭窄(功能有限)的接口——它只能传递备忘录给其他对象。而原发器可以调用一个宽阔(功能强大)的接口,通过这个接口可以访问所有需要的数据,使原发器可以返回先前的状态。理想的情况是,只允许生成本备忘录的那个原发器访问本备忘录的内部状态。
原发器(Originator)
l 创建一个备忘录,记录它当前内部的状态。
l 可以利用一个备忘录来恢复它的内部状态。
看管者(Caretaker)
l 只负责看管备忘录。
l 不可以对备忘录的内容操作或检查。
Memento模式就是解决这种问题的最好办法,Memento的类成为了Originator及Caretaker的媒介,封装保存Originator的备份状体,当Originator被提出备份要求,它就会创建一个Memento对象发挥给Caretaker。Caretaker不可以看到Memento对象的内部信息,需要时,Caretaker可以返回备份的Memento对象给Originator,让它恢复到备份状态。显然,Originator与Memento的关系非常特殊的,它们要分享信息而不让其他类知道。实现的方法因编程语言的不同而不同,C++可以用friend关键字,java及C#就需要将两个类放在同一个包内。
范例
1. 音响均衡器可能会哟很多个华东按钮用来调节声音。一个音效师可以通过拍照面板来保存原来的设定,将图片放在包内,当音效效果不好时,可以从包中取出照片来恢复原来的设定。
2. 现在的主流软件都提供多次取消操作的功能,用java来实现Undo功能,最直接的实现办法是存取对象建造一个Stack堆栈或Vector向量来存放操作变量。Vector对象的存放量没有限制,增加一个Memento对象会使Vector存放量增加。如果你需要控制Vector的存放量,就要手动来完成删除。每一次Undo都把最近的一个Memento返回给Originator,并且在Vector中删除它。
优势和缺陷
Memento模式保存了封装的边界,一个Memento对象是另一种原发器对象的表示,不会被其他代码改动。这种模式简化了原发器对象,Memento只保存原发器的状态。曹勇堆栈备忘对象,可以实现多次取消操作。
应用情景
1. 对象状态的备忘足以使对象可以完全恢复到原来的状态。
2. 使用一个直接的接口来取得状态会使实现细节过程化,这样会打破对象的封装性。