JAVA中的備忘錄模式實例教程
備忘錄模式是一種行為模式。備忘錄模式用於保存對象當前狀態,並且在之後可以再次使用此狀態。備忘錄模式實現的方式需要保證,被保存的對象狀態不能被對象從外部訪問,目的為了被保存的這些對象狀態的完整性。
備忘錄模式通過兩個對象實現:Originator以及Caretaker。Originator類代表了其狀態能夠被存儲並被用於恢複之前的狀態,它使用內部類保存對象的狀態。此內部類就被叫做備忘錄,注意此類是私有的,它不能被其他對象訪問。
Caretaker是一個幫助類,它的職責就是通過備忘錄幫助Originator存儲當前狀態或者恢複重建其之前的狀態。因為備忘錄是Originator的私有類,Caretaker不能訪問它,因此它作為一個對象被存儲在caretaker中。
現實中最好的例子是文本編輯器,它任何時候都存在已經輸入的數據,並且可以使用回退功能恢複之前的存儲(寫作)狀態。我們將實現相同功能並且提供一個任何時候都把輸入、存在內容到文件中的工具集,此外,我們也能恢複上一個存儲(寫作)的狀態。為了簡單,此處沒用更實用任何寫入數據到文件的IO操作。
Originator類
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);
}
}
}
注意備忘錄的內部類及其保存及恢複方法。現在實現Caretaker類
Caretaker類
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);
}
}
注意caretaker對象包含了整個對象形式的存儲狀態,因此它既不能修改被保存對象又對其結構未知。
備忘錄測試類
完整一個簡單地測試程序
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
此模式簡單易實現,但是需要注意的是備忘錄類隻能被Originator對象訪問。在客戶端程序中,使用caretaker對象完成保存或恢複originator對象的狀態。
另外,如果Originator對象有一些屬性不是不可變的,我們需要使用深拷貝或者克隆來避免數據的完整性問題。使用序列化來取得備忘錄模式的實現不失為一般方法,而不是為每一個對象創建一個自己的備忘錄實現。
此模式的缺點是, 如果Originator對象非常巨大,那麼備忘錄對象的大小也會被相應增大,因而需要更多的內存空間。
最後更新:2017-05-23 11:31:44