备忘录模式就是在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能将该对象恢复到原先保存的状态。该模式又叫快照模式。
我们在很多地方可以看到版本快照,很多都是使用的备忘录模式来进行版本的管理。
备忘录模式一般分为三个大类:
========================================================================
我们对于备忘录模式接触的最多的,就是事务的回滚机制,比如mysql的事务回滚是基于日志进行回滚,我们模仿回滚机制来实现一个备忘录模式:
我们首先定义一个日志文档类,就是我们需要去回滚的日志:
package BehavioralPatterns.MementoPattern;
/**
* @author Zeyu Wan
* @version 1.0.0
* @ClassName LogFile.java
* @Description 日志文档
* @createTime 2022年03月17日 16:09:00
*/
public class LogFile {
private String versionNumber;
private String updateDate;
private String doc;
private String changeDate;
private String operator;
public LogFile(String versionNumber,String updateDate,String doc,String changeDate,String operator){
this.changeDate = changeDate;
this.doc = doc;
this.operator = operator;
this.updateDate = updateDate;
this.versionNumber = versionNumber;
}
public String getChangeDate() {
return changeDate;
}
public String getOperator() {
return operator;
}
public String getUpdateDate() {
return updateDate;
}
public String getVersionNumber() {
return versionNumber;
}
public void setChangeDate(String changeDate) {
this.changeDate = changeDate;
}
public void setOperator(String operator) {
this.operator = operator;
}
public void setUpdateDate(String updateDate) {
this.updateDate = updateDate;
}
public void setVersionNumber(String versionNumber) {
this.versionNumber = versionNumber;
}
public String getDoc() {
return doc;
}
public void setDoc(String doc) {
this.doc = doc;
}
@Override
public String toString() {
return "LogFile{" +
"版本号:='" + versionNumber + '\'' +
", 上传时间:='" + updateDate + '\'' +
", 日志内容:='" + doc + '\'' +
", 修改时间:='" + changeDate + '\'' +
", 操作人:='" + operator + '\'' +
'}';
}
}
创建一个备忘录,来对日志进行操作:
package BehavioralPatterns.MementoPattern;
/**
* @author Zeyu Wan
* @version 1.0.0
* @ClassName Memento.java
* @Description 备忘录类
* @createTime 2022年03月17日 16:19:00
*/
public class Memento {
private LogFile logFile;
public Memento (LogFile logFile){
this.logFile = logFile;
}
/**
* 获取日志
* @return 日志文档
*/
public LogFile getLogFile() {
return logFile;
}
/**
* 设置日志文档
* @param logFile 日志文档
*/
public void setLogFile(LogFile logFile) {
this.logFile = logFile;
}
}
定义一个记录者:
package BehavioralPatterns.MementoPattern;
/**
* @author Zeyu Wan
* @version 1.0.0
* @ClassName Originator.java
* @Description 记录者类
* @createTime 2022年03月17日 16:21:00
*/
public class Originator {
private LogFile logFile;
/**
* 获取日志文件
* @return 日志文件
*/
public LogFile getLogFile() {
return logFile;
}
public void setLogFile(LogFile logFile) {
this.logFile = logFile;
}
/**
* 保存备忘录
* 保存备忘录的时候会创建一个备忘录信息,并返回回去,交给管理者处理。
* @return 新建备忘录信息
*/
public Memento saveMemento(){
return new Memento(logFile);
}
/**
* 获取备忘录
* 获取的之后并不是直接返回,而是把备忘录的信息交给现在的文件 this.logFile
* @param memento 备忘录
*/
public void getMemento(Memento memento){
this.logFile = memento.getLogFile();
}
}
记录者除了可以获取和设置日志,还增加了保存备忘录和获取备忘录的功能。
创建一个日志管理员来记录文件信息:
package BehavioralPatterns.MementoPattern;
import javax.jws.Oneway;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author Zeyu Wan
* @version 1.0.0
* @ClassName Caretaker.java
* @Description 管理员类
* 记录文件信息
* @createTime 2022年03月17日 16:26:00
*/
public class Caretaker {
private int cursorIndex = 0;
private final List mementos = new ArrayList();
private final Map mementoMap = new HashMap();
/**
* 添加备忘录
* @param memento 备忘录
*/
public void append(Memento memento){
//把当前备忘录添加到备忘录数组
mementos.add(memento);
//把当前备忘录添加到备忘录map,key是现在的版本号,value是对应的备忘录
mementoMap.put(memento.getLogFile().getVersionNumber(),memento);
cursorIndex++;
}
/**
* 回滚备忘录
* @return 回滚的备忘录
*/
public Memento undoLog(){
if (--cursorIndex <= 0) {
return mementos.get(0);
}
return mementos.get(cursorIndex);
}
/**
* 撤销回滚
* @return 返回回滚之前备忘录
*/
public Memento redoLog(){
if (++cursorIndex>mementos.size()){
return mementos.get(mementos.size()-1);
}
return mementos.get(cursorIndex);
}
/**
* 定向获取备忘录
* @param version 备忘录版本号
* @return 对应的备忘录
*/
public Memento get(String version){
return mementoMap.get(version);
}
}
管理员的核心功能就是记录配置文件信息,也就是备忘录的效果,之后提供可以回滚和获取的方法,拿到备忘录的具体内容。
测试一下:
package BehavioralPatterns.MementoPattern;
/**
* @author Zeyu Wan
* @version 1.0.0
* @ClassName MementoTest.java
* @Description 测试类
* @createTime 2022年03月17日 16:45:00
*/
public class MementoTest {
public static void main(String[] args) {
//创建一个管理员
Caretaker caretaker = new Caretaker();
//创建一个记录者
Originator originator = new Originator();
//添加log
originator.setLogFile(new LogFile("00001","20211211","喵喵喵喵喵","20211211","张三"));
//保存log
caretaker.append(originator.saveMemento());
originator.setLogFile(new LogFile("00002","20211211","汪汪汪汪汪","20211211","张三"));
caretaker.append(originator.saveMemento());
originator.setLogFile(new LogFile("00003","20211211","嘎嘎嘎嘎嘎","20211211","张三"));
caretaker.append(originator.saveMemento());
originator.setLogFile(new LogFile("00004","20211211","咕咕咕咕咕","20211211","张三"));
caretaker.append(originator.saveMemento());
System.out.println("开始回滚===============");
originator.getMemento(caretaker.undoLog());
System.out.println(originator.getLogFile());
System.out.println("开始回滚===============");
originator.getMemento(caretaker.undoLog());
System.out.println(originator.getLogFile());
System.out.println("开始撤销回滚===============");
originator.getMemento(caretaker.redoLog());
System.out.println(originator.getLogFile());
System.out.println("开始获取版本:00002===============");
originator.getMemento(caretaker.get("00002"));
System.out.println(originator.getLogFile());
}
}
优点 :
缺点: