定义与特点
- 定义:在不破坏封装性的前提下捕获一个对象内部的状态,并在对象之外保存这个状态,以便对象以后恢复到这一状态。备忘录模式可以使系统恢复到某一历史时期的状态,又称快照模式
参与角色
- Originator(发起人):一个普通类,可以创建一个备忘录,提供存储当前内部状态和恢复内部状态的功能,它可以访问备忘录中的所有信息。
- Memento(备忘录):存储发起人的内部状态,根据发起人来决定保存哪些内部状态,在需要的时候提供这些状态给发起人。需要注意的是,除了发起人本身与负责人类之外,备忘录对象不能直接供其他类使用。
- Caretaker(负责人):负责人又称为管理者,它负责保存备忘录。可以存储一个或多个备忘录对象,它只负责存储对象,而不能修改对象,也无须知道对象的实现细节。
- 类结构图
结构代码示例
定义备忘录
//备忘录 class Memento { private String state; public Memento(String state) { this.state = state; } public void setState(String state) { this.state = state; } public String getState() { return state; } }
定义发起人
//发起人 class Originator { private String state; public void setState(String state) { this.state = state; } public String getState() { return state; } public Memento createMemento() { return new Memento(state); } public void restoreMemento(Memento m) { this.setState(m.getState()); } }
定义管理者
//管理者 class Caretaker { private Memento memento; public void setMemento(Memento m) { memento = m; } public Memento getMemento() { return memento; } }
调用测试程序
public class MementoTest { public static void main(String[] args) { Originator or = new Originator(); or.setState("S0"); System.out.println("初始状态:" + or.getState()); Caretaker cr = new Caretaker(); cr.setMemento(or.createMemento()); // 保存状态 or.setState("S1"); System.out.println("新的状态:" + or.getState()); or.restoreMemento(cr.getMemento()); // 恢复状态 System.out.println("恢复状态:" + or.getState()); } } //输出结果 初始状态:S0 新的状态:S1 恢复状态:S0
案例分析
以电脑文件备份还原为例,这里涉及到:文件(被备份对象)、电脑(发起备份人)、备份位置(Disk硬盘)
定义被备份对象
class MyFile { private String fileName; private String fileType; public MyFile(String fileName, String fileType) { this.fileName = fileName; this.fileType = fileType; } //省略getter&setter..... @Override public String toString() { return "MyFile [fileName=" + fileName + ", fileType=" + fileType + "]"; } }
定义备忘录
class FileMemento { private MyFile myFile; public FileMemento(MyFile myFile) { this.myFile = myFile; } public MyFile getMyFile() { return myFile; } public void setMyFile(MyFile myFile) { this.myFile = myFile; } }
定义发起人
class Windows { private MyFile myFile; public MyFile getMyFile() { return myFile; } public void setMyFile(MyFile myFile) { this.myFile = myFile; } public FileMemento createMemento() { return new FileMemento(myFile); } public void restoreMemento(FileMemento fileMemento) { this.setMyFile(fileMemento.getMyFile()); } }
定义管理者
class DiskF { private FileMemento fileMemento; public void setFileMemento(FileMemento fileMemento) { this.fileMemento = fileMemento; } public FileMemento getFileMemento() { return fileMemento; } }
调用客户端
public class MementoTest { public static void main(String[] args) { MyFile myFile = new MyFile("天龙八部","mp4"); MyFile myFile2 = new MyFile("天龙八部bak","mp4"); Windows windows = new Windows(); windows.setMyFile(myFile); System.out.println("初始状态:" + windows.getMyFile()); DiskF disk = new DiskF(); disk.setFileMemento(windows.createMemento()); // 保存状态 windows.setMyFile(myFile2); System.out.println("新的状态:" + windows.getMyFile()); windows.restoreMemento(disk.getFileMemento()); // 恢复状态 System.out.println("恢复状态:" + windows.getMyFile()); } } //执行结果 初始状态:MyFile [fileName=天龙八部, fileType=mp4] 新的状态:MyFile [fileName=天龙八部bak, fileType=mp4] 恢复状态:MyFile [fileName=天龙八部, fileType=mp4]
- 如果需要备份多次,则需要将FileMemento单类改为List或Map集合复杂类型,确定好下标(序号)或备份标签(key)方恢复到指定的版本。
总结
优点
- 提供了一种可以恢复状态的机制。当用户需要时能够比较方便地将数据恢复到某个历史的状态。
- 实现了内部状态的封装。除了创建它的发起人之外,其他对象都不能够访问这些状态信息。
- 简化了发起人类。发起人不需要管理和保存其内部状态的各个备份,所有状态信息都保存在备忘录中,并由管理者进行管理,这符合单一职责原则
- 缺点
实现复杂,如果需要维护多个备份,可能会影响系统的性能。
适用场景
- 需要保存和恢复数据的相关状态场景。
- 提供一个可回滚(rollback)的功能场景。
- 需要监控的副本场景。