一、概述
备忘录模式(Memento Pattern)是在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原先的状态。
其实很多应用软件都提供了这项功能,如 Word、记事本、Photoshop、Eclipse 等软件在编辑时按 Ctrl+Z 组合键时能撤销当前操作,使文档恢复到之前的状态;还有在 IE 中的后退键、数据库事务管理中的回滚操作、玩游戏时的中间结果存档功能、数据库与操作系统的备份操作、棋类游戏中的悔棋功能等都属于这类。
备忘录模式的4个角色:
- 备忘录角色(Memento):负责存储Originator对象的内部状态,并可以防止Originator以外的其他对象访问备忘录。
- 备忘录发起角色(Originator):负责创建一个备忘录用以记录当前时刻它的内部状态,并可以使用备忘录恢复内部状态。
- 备忘录管理角色(Caretaker):负责保存好备忘录。
二、优缺点
优点: 1、给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。 2、实现了信息的封装,使得用户不需要关心状态的保存细节。
缺点:消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。
三、实现方式
说起备忘录模式的案例,对于开发者来说肯定会想到Git版本控制工具,下面简单模拟Git实现备忘录模式。
备忘录类
public class Memento {
private String version;
private String creator;
private Long createTime;
public Memento(String version, String creator, Long createTime) {
this.version = version;
this.creator = creator;
this.createTime = createTime;
}
public String getVersion() {
return version;
}
public String getCreator() {
return creator;
}
public Long getCreateTime() {
return createTime;
}
}
发起人类
public class Originator {
private String version;
private String creator;
private Long createTime;
public Originator() {
}
public Originator(String version, String creator, Long createTime) {
this.version = version;
this.creator = creator;
this.createTime = createTime;
}
//创建版本
public Memento createMemento(){
return new Memento(version,creator,createTime);
}
//回退版本
public void restoreMemento(Memento memento){
this.version = memento.getVersion();
this.createTime = memento.getCreateTime();
this.creator = memento.getCreator();
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getCreator() {
return creator;
}
public void setCreator(String creator) {
this.creator = creator;
}
public Long getCreateTime() {
return createTime;
}
public void setCreateTime(Long createTime) {
this.createTime = createTime;
}
@Override
public String toString() {
return "版本:'" + version + ''' +
", 创建者:'" + creator + ''' +
", 创建时间戳:" + createTime ;
}
}
备忘录管理类
public class Caretaker {
//保存版本的集合
private List<Memento> mementos = new ArrayList<>();
//保存版本
public void add(Memento memento){
mementos.add(memento);
}
//获取版本
public Memento get(int index){
return mementos.get(index);
}
}
客户端
public class Client {
public static void main(String[] args) {
Originator originator = new Originator("v1.0", "syx", System.currentTimeMillis());
Caretaker caretaker = new Caretaker();
System.out.println("保存版本v1.0");
caretaker.add(originator.createMemento());
System.out.println("当前版本:" + originator.toString());
originator.setVersion("v1.1");
originator.setCreateTime(System.currentTimeMillis());
System.out.println("保存版本v1.1");
caretaker.add(originator.createMemento());
System.out.println("当前版本:" + originator.toString());
System.out.println("回退版本至v1.0");
originator.restoreMemento(caretaker.get(0));
System.out.println("当前版本:" + originator.toString());
}
}
结果输出
保存版本v1.0
当前版本:版本:'v1.0', 创建者:'syx', 创建时间戳:1663825457900
保存版本v1.1
当前版本:版本:'v1.1', 创建者:'syx', 创建时间戳:1663825457901
回退版本至v1.0
当前版本:版本:'v1.0', 创建者:'syx', 创建时间戳:1663825457900
四、常见应用场景
● 需要保存和恢复数据的相关状态场景。
● 提供一个可回滚(rollback)的操作。
● 需要监控的副本场景中。
● 数据库连接的事务管理就是用的备忘录模式。