目的
在不违反封装的情况下,捕获对象的内部状态并将其外部化,以便稍后将该对象还原到此状态。
现实中最好的例子之一是文本编辑器,我们可以随时保存它的数据,并使用“撤消”将其恢复到以前保存的状态。
也称为
令牌(taken)
结构
参与者
1.Memento
- 该组件存储Originator对象的内部状态。纪念品可以根据发起人的判断,尽可能多地存储发起人的内部状态。
- 此组件可防止发件人以外的对象访问。Mementos有效地有两个接口。看守人看到了Memento的狭窄界面 - 它只能将纪念品传递给其他物品。相比之下,Originator看到了一个宽广的界面,可以让它访问将自身恢复到之前状态所需的所有数据。理想情况下,只允许制作纪念品的发起人进入纪念品的内部状态。
2.Originator(创建者)
- 该组件创建一个包含其当前内部状态快照的Memento 。
3.Caretaker(看守者)
源代码
备忘录模式是通过两个对象实现的——创建者(Originator)和看守者(Caretaker)。
Originator是需要保存和恢复其状态的对象,它使用一个内部类来保存对象的状态。内部类称为memento,它是私有的,因此不能从其他对象访问它。
Caretaker是帮助类,负责通过Memento对象存储和恢复Originator的状态。由于Memento对Originator是私有的,因此Caretaker无法访问它,它作为对象存储在Caretaker中。第1步:让我们创建Originator Class。
public class FileWriterUtil { private String fileName; private StringBuilder content; public FileWriterUtil(String file) { this.fileName = file; this.content = new StringBuilder(); }
@Override public String toString() { return this.content.toString(); } public void write(String str) { content.append(str); } public Memento save() { return new Memento(this.fileName, this.content); } public void undoToLastSave(Object obj) { Memento memento = (Memento) obj; this.fileName = memento.fileName; this.content = memento.content; } private class Memento { private String fileName; private StringBuilder content; public Memento(String file, StringBuilder content) { this.fileName = file; //notice the deep copy so that Memento and FileWriterUtil content variables don 't refer to same object this.content = new StringBuilder(content); } } }
|
注意Memento内部类以及save和undo方法的实现。现在我们可以继续实现Caretaker类。
第2步:创建Caretaker类
public class FileWriterCaretaker { private Object obj;
public void save(FileWriterUtil fileWriter) { this.obj = fileWriter.save(); } public void undo(FileWriterUtil fileWriter) { fileWriter.undoToLastSave(obj); } }
|
注意, caretaker对象是以对象的形式包含保存的状态,因此它不能更改其数据,也不了解其结构。
第3步:让我们测试memento模式。编写一个简单的测试程序,它将使用我们的memento实现。
public class FileWriterClient { public static void main(String args) { FileWriterCaretaker caretaker = new FileWriterCaretaker(); FileWriterUtil fileWriter = new FileWriterUtil("data.txt"); fileWriter.write("First Set of Data\n"); System.out.println(fileWriter + "\n\n"); // lets save the file caretaker.save(fileWriter); //now write something else fileWriter.write("Second Set of Data\n"); //checking file contents System.out.println(fileWriter + "\n\n"); //lets undo to last save caretaker.undo(fileWriter); }
|
适用性
使用Memento模式时
- 必须保存对象状态的快照,以便以后可以将其恢复到该状态