备忘录模式-Memento Pattern
别名:快照模式-Snapshop Pattern 或令牌模式- Token Pattern
是什么?
是指在不破坏封装的前提下,捕获一个对象的内部状态,并且在对象之外保存这个状态,这样我们就可以在需要的时候将该对象恢复到原先保存的状态了。
可以做什么?
可以提供一种“后悔药”的机制,当你需要让对象返回之前的状态时,例如:你的用户请求“撤销”,就使用备忘录模式。
怎么实现的?
它通过存储系统中各个历史状态的快照,使得我们可以在任意时刻将系统回滚到历史状态。
通过堆栈方式:
应用场景
- 编辑文档写文章的时候,经常写错,需要撤销的操作(Ctrl+Z),有这种需求的时候可以就用该模式。
- 保存游戏进度,比如闯关模式,经常会挂掉,需要恢复到一个时间点。
- SVN、Git 等都提供了历史版本的管理功能
- 服务器的快照功能也可以让我们回退到历史状态
- 应用场景总结:
1.需要保存历史快照的场景
2.希望在对象之外保存状态,且除了自己其他对象无法访问状态的具体保存内容
优缺点
- 优点:简化了发起人的职责,将状态的存储和获取进行了隔离,而且客户端无需关心状态的保存细节。
- 缺点:消耗资源,如果每个快照的内容都非常大,会消耗大量内存。
代码实现示例
文档类-Document
package com.muse.patterns.memento;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @description 文档类
**/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Document {
// 文档的内容
private String content;
public void print() {
System.out.println("content=" + content);
}
}
备忘录-Memento
package com.muse.patterns.memento;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @description 备忘录
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Memento {
// 文档内容
public String content;
}
备忘录管理类-MememtoManager
package com.muse.patterns.memento;
import java.util.Stack;
/**
* @description 备忘录管理类
*/
public class MementoManager {
// 记录备忘录信息
private Stack<MementomementoStack = new Stack<>();
// 保存备忘录
public void save(Document document) {
Memento memento = new Memento(document.getContent());
mementoStack.add(memento);
}
// 撤销操作ctrl+z
public Document cancel() {
Memento memento = mementoStack.pop();
Document document = new Document();
document.setContent(memento.getContent());
return document;
}
}
备忘录测试类-MementoTest
package com.muse.patterns.memento;
/**
* 备忘录测试类
*/
public class MementoTest {
public static void main(String[] args) {
MementoManager mementoManager = new MementoManager();
System.out.println("-----执行文档修改操作-----");
Document document = new Document();
document.setContent("a");
document.print();
mementoManager.save(document);
document.setContent("b");
document.print();
mementoManager.save(document);
document.setContent("c"); // 修改后,发现写错了,想要回撤到上一个保存点
document.print();
System.out.println("-----执行第一次撤销操作-----");
document = mementoManager.cancel();
document.print();
System.out.println("-----执行第二次撤销操作-----");
document = mementoManager.cancel();
document.print();
}
}