备忘录模式
备忘录模式-在不破坏封装的条件下,通过备忘录对象(Memento)存储另外一个对象内部状态的快照,在将来合适的时候把这个对象还原到存储起来的状态。类型:行为型
模式和结构定义
- Originator:发起者,负责创建一个备忘录,并且可以记录、恢复自身的内部状态。可以根据需要决定Memento保存自身的那些内部状态
- Memento:备忘录,用于存储Originator的状态,防止Originator以外的的对象访问Memento
- Caretaker:备忘录管理者,负责存储备忘录,不能对备忘录的内容进行操作和访问,只能够将备忘录传递给其他对象。
应用实例
下面使用备忘录模式实现一个文章系统写文章时,可回退到最近的一个编辑状态的功能
文章类
/**
* 文章类
*
* @author shengyong.huang
* @date 2020-07-25
*/
public class Article {
private String title;
private String content;
private String userName;
public Article(String title, String content, String userName) {
this.title = title;
this.content = content;
this.userName = userName;
}
public ArticleMemento saveToMemento() {
return new ArticleMemento(title, content, userName);
}
public void undoFromMemento(ArticleMemento memento) {
this.title = memento.getTitle();
this.content = memento.getContent();
this.userName = memento.getUserName();
}
@Override
public String toString() {
return "Article{" +
"title='" + title + '\'' +
", content='" + content + '\'' +
", userName='" + userName + '\'' +
'}';
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
文章备忘录类
/**
* 文章备忘录类
*
* @author shengyong.huang
* @date 2020-07-25
*/
public class ArticleMemento {
private String title;
private String content;
private String userName;
public ArticleMemento(String title, String content, String userName) {
this.title = title;
this.content = content;
this.userName = userName;
}
public String getTitle() {
return title;
}
public String getContent() {
return content;
}
public String getUserName() {
return userName;
}
}
文章备忘录管理类
/**
* 文章备忘录管理类
*
* @author shengyong.huang
* @date 2020-07-25
*/
public class ArticleMementoManager {
private static Stack<ArticleMemento> articleMementos = new Stack<>();
public static void addMemento(ArticleMemento articleMemento) {
articleMementos.push(articleMemento);
}
public static ArticleMemento getNearestMemento() {
return articleMementos.pop();
}
}
测试方法
/**
* 测试方法
*
* @author shengyong.huang
* @date 2020-07-25
*/
public class TestMain {
public static void main(String[] args) {
Article article = new Article("备忘录模式1","内容1","小王");
// 自动存储备忘录
ArticleMementoManager.addMemento(article.saveToMemento());
System.out.println("第一次编辑:"+article);
// 标题写错了,修改一下
article.setTitle("备忘录模式");
// 继续编辑内容
article.setContent("备忘录模式-在不破坏封装的条件下,通过备忘录对象(Memento)存储另外一个对象内部状态的快照,在将来合适的时候把这个对象还原到存储起来的状态。");
// 自动存储备忘录
ArticleMementoManager.addMemento(article.saveToMemento());
System.out.println("第二次编辑:"+article);
// 继续修改
article.setTitle("备忘录模式##");
article.setContent("xxxx");
article.setContent("小田");
System.out.println("第三次编辑:"+article);
// 发现编辑错了,回退
article.undoFromMemento(ArticleMementoManager.getNearestMemento());
System.out.println("回退:"+article);
}
}
结果展示
第一次编辑:Article{title='备忘录模式1', content='内容1', userName='小王'}
第二次编辑:Article{title='备忘录模式', content='备忘录模式-在不破坏封装的条件下,通过备忘录对象(Memento)存储另外一个对象内部状态的快照,在将来合适的时候把这个对象还原到存储起来的状态。', userName='小王'}
第三次编辑:Article{title='备忘录模式##', content='小田', userName='小王'}
回退:Article{title='备忘录模式', content='备忘录模式-在不破坏封装的条件下,通过备忘录对象(Memento)存储另外一个对象内部状态的快照,在将来合适的时候把这个对象还原到存储起来的状态。', userName='小王'}
优点和不足
优点
- 为用户提供一种可恢复机制
- 存档信息的封装
缺点 - 资源占用,如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。当然也可以选择持久化
使用场景
- 保存及恢复数据相关业务场景
- 后悔的时候,即想恢复到之前的状态
- IDEA中的localHistory功能,本地保存的某个时刻代码的快照
- wps也有类似快照功能