备忘录模式(Memento Pattern)
备忘录模式(Memento Pattern)又称快照模式(Snapshop Pattern),属于行为型模式。
什么是备忘录模式?
备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象。(后悔药模式)
UML
角色
- 发起(Originator)角色:负责组织整个备忘录的全过程,通过创建、导入备忘录来备份、恢复数据。
- 备忘录(Memento)角色:负责存储发起角色对象的内部状态,并可防止对应发起角色以外的其他对象访问备忘录。备忘录有两个接口,管理者只能看到备忘录的窄接口,它只能将备忘录传递给其他对象。发起者能够看到一个宽接口,允许它访问返回到先前状态所需的所有数据。
- 管理者(Caretaker):负责保存备忘录Memento,不能对备忘录的内容进行操作或检查。
应用
使用模板
public class MementoPattern {
public static void main(String[] args) {
//创建管理者,用来管理被保存的备忘录
Caretaker caretaker = new Caretaker();
//创建发起者
Originator originator = new Originator();
//设置发起者的状态
originator.setState("A");
originator.print();
System.out.println("修改");
caretaker.setMemento(originator.createMemento());
originator.setState("B");
originator.print();
System.out.println("撤销");
//执行撤销操作
originator.restoreMemento(caretaker.getMemento());
originator.print();
}
}
/
//发起者
class Originator {
//需要保存的属性
private String state;
public String getState() { return state; }
public void setState(String state) { this.state = state; }
//创建备忘录
public Memento createMemento() { return new Memento(state); }
//恢复备忘录,将Memento导入并将相关数据恢复
public void restoreMemento(Memento memento) { this.state = memento.getState(); }
//显示数据
public void print() { System.out.println("state = " + getState()); }
}
/
//备忘录
class Memento {
//备忘录数据(备忘录数据可以为复杂数据)
private String state;
//创建时导入数据
public Memento(String state) { this.state = state; }
//获取数据
public String getState() { return state; }
}
/
//管理者
class Caretaker {
//备忘录对象(可以通过某些数据结构实现保存更多的备忘录数据)
private Memento memento;
//获取备忘录
public Memento getMemento() { return memento; }
//设置备忘录
public void setMemento(Memento memento) { this.memento = memento; }
}
为什么要使用备忘录模式?
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。
优点:
- 实现了信息的封装,使得用户不需要关心状态的保存细节。
- 给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。
缺点:
- 如果成员变量过多或者快照过多,会占用比较大的资源。
怎样使用备忘录模式?
使用场景
- 撤销操作:保存 / 恢复 数据 的相关业务场景;
如:在 Word 中编写文档 ,如果想要撤销之前的 输入 / 删除操作,使用 Ctrl + Z 执行撤销操作 ; - 状态恢复:在 " 后悔 " 的时候 , 将对象恢复到之前的状态 ;
如 : 游戏中的存档使用 ;
在JDK中的使用
java.util.Date
在使用构造器Date(long date)
时,通过传入一个数据的方式将该部分数据进行备份。
调用这个构造器的类本身,即扮演了发起者角色,又扮演了管理者角色。
而这个类,便对应了备忘录这个角色。
public class Date
implements java.io.Serializable, Cloneable, Comparable<Date>
{
// 用于存储状态
private transient long fastTime;
//构造器,保存时间
public Date(long date) {
fastTime = date;
}
}