写在前面
嗨,伙计!刷到这篇文章就是有缘人,在阅读这篇文章前我有一些建议:
- 本篇文章大概3000多字,预计阅读时间长需要4分钟。
- 本篇文章的实战性、理论性较强,是一篇质量分数较高的技术干货文章,建议收藏起来,方便时常学习与回顾,温故而知新。
- 创作不易,免费的点赞、关注,请走上一走,算是对博主一些鼓励,让我更有动力输出更多的干货内容。
- 另外,UML类图是一个非常好的东西,要会看,如果会画就更好了,一图胜千言。
什么是备忘录模式
备忘录模式,又称之为快照模式(Snapshop Pattern),是一种行为型设计模式,,它允许在不破坏对象封装性的前提下,捕获并保存一个对象的内部状态,以便在需要时恢复该对象到原先的状态。备忘录模式可以为我们提供一种"后悔药"的机制,它通过存储系统中各个历史状态的快照,使得我们可以在任一时刻将系统回滚到历史状态。
备忘录模式的核心原理
备忘录模式的核心原理是在不破坏封装性的前提下,将一个对象的状态保存在一个备忘录对象中,并在需要时恢复该对象的状态。备忘录模式包含三个角色:发起人、备忘录和管理者:
备忘录模式的主要角色包括:
- 发起人(Originator):发起人角色记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能。
- 备忘录(Memento):备忘录角色负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人
- 管理者(Caretaker):管理者角色对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问与修改。
备忘录模式如何实现
需求描述
经常使用在线笔记类软件进行文本内容编辑的小伙伴肯定有这样的印象:在编写一段文本的时候,使用笔记软件可以手动或者自动地保存文本内容,这里的每一次执行自动或手动的保存就可以理解为当前文本的一次快照,在文本编写的过程中,如果有需要,可以回退到任意历史版本。
实现方法
1、TextContent.java:文本内容实体类,即备忘录发起人角色,除了本身的业务内容外,还具有创建和回退的功能;
java
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* 文本内容
*/
@Data
@AllArgsConstructor
public class TextContent {
private String title;
private String content;
private Date createTime;
/**
* 创建备忘录
* @return
*/
public TextContentMemento create(){
TextContentMemento textContentMemento = new TextContentMemento(this.title, this.content, this.createTime);
return textContentMemento;
}
/**
* 回退指定备忘录内容
* @param textContentMemento
*/
public void rollback(TextContentMemento textContentMemento){
this.title=textContentMemento.getTitle();
this.content=textContentMemento.getContent();
this.createTime=textContentMemento.getCreateTime();
}
/**
* 对象信息展示
*/
public void show(){
System.out.println("标题:"+this.title);
System.out.println("内容:"+this.content);
}
}
2、TextContentMemento.java:文本内容备忘录实体类,即具体的备忘录角色,与文本内容实体类有相的属性;
java
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* 文本内容备忘录
*/
@Data
@AllArgsConstructor
public class TextContentMemento {
private String title;
private String content;
private Date createTime;
}
3、TextContentCaretaker.java:文本内容备忘录的管理类,即备忘录管理者角色,可以获取指定备忘录内容、添加备忘录内容、查看备忘的版本数量;
java
/**
* 文本内容备忘录的管理者][
*/
public class TextCaretaker {
private List<TextContentMemento> list=new ArrayList<>();
/**
* 备忘录中版本数量
* @return
*/
public Integer size(){
return this.list.size();
}
/**
* 获取指定版本备忘录
* @param index
* @return
*/
public TextContentMemento get(Integer index){
return this.list.get(index);
}
/**
* 添加指定备忘录内容
* @param textContentMemento
*/
public void add(TextContentMemento textContentMemento){
this.list.add(textContentMemento);
}
}
4、编写客户端,模拟多个版本文本内容编辑并回退到指定版本;
java
public class Client {
public static void main(String[] args) {
TextContent textContent = new TextContent("设计模式之备记录模式v1", "this is v1", new Date());
System.out.println("v1:");
textContent.show();
TextCaretaker textCaretaker = new TextCaretaker();
//创建并添加第一个快照
TextContentMemento textContentMemento = textContent.create();
textCaretaker.add(textContentMemento);
textContent.setTitle("设计模式之备记录模式v2");
textContent.setContent("this is v2");
textContent.setCreateTime(new Date());
System.out.println("v2:");
textContent.show();
//创建并添加第二个快照
textContentMemento=textContent.create();
textCaretaker.add(textContentMemento);
//回退第一个快照的内容
textContentMemento=textCaretaker.get(0);
textContent.rollback(textContentMemento);
System.out.println("回退v1:");
textContent.show();
}
}
备忘录模式适用哪些场景
备忘录模式适用于以下业务场景:
- 保存和恢复对象状态:在软件中,有些对象的状态需要在不同时间点进行保存和恢复。备忘录模式可以捕获对象的状态,并在需要时恢复对象到先前的状态。例如,在浏览器中的后退功能,或者在编辑工具中的撤销操作等。
- 实现可回滚的撤销操作:在软件中,撤销操作是一个常见的功能。备忘录模式可以保存对象的状态,以便在撤销操作时恢复对象到先前的状态。例如,在Word中编写文档,如果想要撤销之前的输入/删除操作,可以使用备忘录模式实现可回滚的撤销操作。
总之,备忘录模式的特点很明显,也很简单,适用于需要保存和恢复对象状态的场景,如撤销操作、游戏存档、事务回滚等类似场景。
备忘录模式的优点和缺点
优点
- 可以随时保存一个对象的状态,并在需要时恢复到该状态,提高了程序的灵活性和可维护性;
- 发起人和备忘录之间的封装使得客户端无法直接访问备忘录,从而更好地保护了对象的状态信息;
- 管理者可以管理多个备忘录,提供了更好的历史记录和回滚功能。
缺点
- 备忘录模式的缺点包括:如果备忘录对象过多或者状态信息过于复杂,会占用较多的内存空间;
- 捕获和恢复一个对象的状态需要时间和资源,可能会影响程序的性能;
总结
备忘录模式的本质是在不破坏封装性的前提下,捕获和存储一个对象的内部状态,并在需要时将对象恢复到先前的状态。它可以将对象的状态封装在备忘录对象中,使得对象的状态对外部对象是不可见的。同时,通过引入备忘录类作为中介,发起人对象可以将其状态保存到备忘录对象中,而不需要将其私有状态暴露给其他对象。通过使用备忘录模式,我们可以提高软件的灵活性和可维护性,使得软件更加健壮和易于使用。