Java中的Memento设计模式
备忘录设计模式是行为设计模式之一。
当我们要保存对象的状态以便以后可以恢复时,可以使用Memento设计模式。
使用Memento模式以这种方式实现该目的,即无法在对象外部访问对象的已保存状态数据,从而保护了已保存状态数据的完整性。
备忘录设计模式
Memento设计模式由两个对象实现-" Originator"和" Caretaker"。
发起者是需要保存和恢复其状态的对象,它使用内部类来保存对象的状态。
内部类称为Memento,它是私有的,因此无法从其他对象访问。
Caretaker是帮助程序类,负责通过Memento对象存储和恢复发起者的状态。
由于Memento对发起者是私有的,因此看守者无法访问它,并且将其作为对象存储在看守者中。
备忘录设计模式Java
现实生活中最好的示例之一是文本编辑器,我们可以其中随时保存数据,并使用undo将其还原到以前的保存状态。
我们将实现相同的功能,并提供一个实用程序,使我们可以随时将内容写入并保存到文件中,并将其恢复到上次保存的状态。
为简单起见,我将不使用任何IO操作将数据写入文件。
备忘录模式发起者类
package com.theitroad.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.theitroad.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.theitroad.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模式是简单且易于实现的,需要注意的一件事是Memento类应该只能由Originator对象访问。
同样在客户端应用程序中,我们应该使用看守对象来保存和还原发起者状态。
同样,如果Originator对象具有不可变的属性,我们应该使用深层复制或者克隆来避免数据完整性问题,就像我在上面的示例中使用的那样。
我们可以使用序列化来实现更通用的memento模式实现,而不是Memento模式实现,因为每个对象都需要拥有自己的Memento类实现。
缺点之一是,如果Originator对象非常大,那么Memento对象的大小也会很大,并占用大量内存。