memento模式
记忆模式是行为设计模式之一 。 当我们要保存对象的状态以便以后可以恢复时,可以使用Memento设计模式。 使用Memento模式以这种方式实现该目的,即无法在对象外部访问对象的已保存状态数据,这可以保护已保存状态数据的完整性。
Memento模式通过两个对象实现-Originator和Caretaker 。 发起者是需要保存和恢复其状态的对象,并且它使用内部类来保存对象的状态。 内部类称为Memento及其私有类,因此无法从其他对象访问它。
Caretaker是帮助程序类,负责通过Memento对象存储和还原发起者的状态。 由于Memento对发起者是私有的,因此看守者无法访问它,并且将其作为对象存储在看守者中。
现实生活中最好的示例之一是文本编辑器,我们可以在其中随时保存其数据,并使用undo将其还原到以前的保存状态。 我们将实现相同的功能,并提供一个实用程序,使我们可以随时将内容写入并保存到文件中,并将其恢复到上次保存的状态。 为简单起见,我将不使用任何IO操作将数据写入文件。
发起者类
package com.journaldev.design.memento;
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方法的实现。 现在,我们可以继续实施看守类。
看守班
package com.journaldev.design.memento;
public class FileWriterCaretaker {
private Object obj;
public void save(FileWriterUtil fileWriter){
this.obj=fileWriter.save();
}
public void undo(FileWriterUtil fileWriter){
fileWriter.undoToLastSave(obj);
}
}
请注意,看守对象包含对象形式的保存状态,因此它不能更改其数据,也不知道其结构。
纪念品测试班
让我们编写一个简单的测试程序,该程序将使用我们的memento实现。
package com.journaldev.design.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);
//checking file content again
System.out.println(fileWriter+"\n\n");
}
}
上面程序的输出是:
First Set of Data
First Set of Data
Second Set of Data
First Set of Data
该模式简单且易于实现,需要注意的一件事是Memento类应仅对Originator对象可访问。 同样在客户端应用程序中,我们应该使用看守对象来保存和还原发起者状态。
同样,如果Originator对象具有不可变的属性,我们应该使用深层复制或克隆来避免数据完整性问题,就像我在上面的示例中使用的那样。 我们可以使用序列化来实现更通用的memento模式实现,而不是Memento模式实现,因为每个对象都需要拥有自己的Memento类实现。
缺点之一是,如果Originator对象非常大,那么Memento对象的大小也会很大,并占用大量内存。
翻译自: https://www.javacodegeeks.com/2013/08/memento-design-pattern-in-java-example-tutorial.html
memento模式