《设计模式入门》 21.备忘录模式

备忘录模式就是在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能将该对象恢复到原先保存的状态。该模式又叫快照模式。

我们在很多地方可以看到版本快照,很多都是使用的备忘录模式来进行版本的管理。

备忘录模式一般分为三个大类:

  • 发起人(Originator)角色:记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,它可以访问备忘录里的所有信息。
  • 备忘录(Memento)角色:负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人。
  • 管理者(Caretaker)角色:对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问与修改。

========================================================================

我们对于备忘录模式接触的最多的,就是事务的回滚机制,比如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;}@Overridepublic 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();//添加logoriginator.setLogFile(new LogFile("00001","20211211","喵喵喵喵喵","20211211","张三"));//保存logcaretaker.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());}
}

 

优点 :

  1. 提供了一种可以恢复状态的机制。当用户需要时能够比较方便地将数据恢复到某个历史的状态。
  2. 实现了内部状态的封装。除了创建它的发起人之外,其他对象都不能够访问这些状态信息。
  3. 简化了发起人类。发起人不需要管理和保存其内部状态的各个备份,所有状态信息都保存在备忘录中,并由管理者进行管理,这符合单一职责原则。

缺点:

  1. 资源消耗大。如果要保存的内部状态信息过多或者特别频繁,将会占用比较大的内存资源。


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部