备忘录模式

定义

保存一个对象的某个状态,以便于在适当的时候恢复对象。
“后悔药”
行为型

适用场景

  • 保存及恢复数据相关业务场景
  • 后悔的时候,即像恢复到之前的状态

优点和缺点

优点

  • 为用户提供一种可恢复机制
  • 存档信息的封装

缺点

  • 资源占用。如果类的成员过多,势必会占用比较大大的资源,而且每一次保存都会消耗一定的内存。

结构

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

代码实现

假设一个场景,我们有一个文档,需要保存不同的版本内容,方便进行回滚操作
创建发起人角色:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class Word {

private String title;
private String content;

public Word(String title, String content) {
this.title = title;
this.content = content;
}

public String getTitle() {
return title;
}

public String getContent() {
return content;
}

public void setTitle(String title) {
this.title = title;
}

public void setContent(String content) {
this.content = content;
}
//构建需要保存的备忘录对象,或者直接存数据库
public WordMemento saveToMemento(){
return new WordMemento(this.title,this.content);
}
//回退
public void undoFormMemento(WordMemento wordMemento){
this.title = wordMemento.getTitle();
this.content = wordMemento.getContent();
}

@Override
public String toString() {
return "Word{" +
"title='" + title + '\'' +
", content='" + content + '\'' +
'}';
}
}

创建备忘录角色:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class WordMemento {

private String title;
private String content;

public WordMemento(String title, String content) {
this.title = title;
this.content = content;
}

public String getTitle() {
return title;
}

public String getContent() {
return content;
}

@Override
public String toString() {
return "WordMemento{" +
"title='" + title + '\'' +
", content='" + content + '\'' +
'}';
}
}

创建管理者角色:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class WordMementoManager {

private final Stack<WordMemento> stack = new Stack<>();

//返回备忘录保存的上一个版本
public WordMemento getMemento(){
return stack.pop();
}
public void addMemento(WordMemento wordMemento){
stack.push(wordMemento);
}

}

测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class Test {

public static void main(String[] args) {
WordMementoManager wordMementoManager = new WordMementoManager();
Word word = new Word("java设计模式A","设计模式内同A");
System.out.println("创建文档,文档内容:"+word);
WordMemento wordMemento = word.saveToMemento();
wordMementoManager.addMemento(wordMemento);
System.out.println("保存第一版文档,文档内容:"+wordMemento);

System.out.println("修改文档");

word.setTitle("java设计模式B");
word.setContent("设计模式内同B");
System.out.println("第二版文档,文档内容:"+word);
WordMemento wordMemento1 = word.saveToMemento();
wordMementoManager.addMemento(wordMemento1);
System.out.println("保存第二版文档,文档内容:"+wordMemento1);

word.setTitle("java设计模式C");
word.setContent("设计模式内同C");
System.out.println("第三版文档,文档内容:"+word);

System.out.println("----------------------------------");

WordMemento memento = wordMementoManager.getMemento();
word.undoFormMemento(memento);
System.out.println("文档回退,回退后内容:"+word);

WordMemento memento1 = wordMementoManager.getMemento();
word.undoFormMemento(memento1);
System.out.println("文档再次回退,回退后内容:"+word);

}

}

结果:

1
2
3
4
5
6
7
8
9
创建文档,文档内容:Word{title='java设计模式A', content='设计模式内同A'}
保存第一版文档,文档内容:WordMemento{title='java设计模式A', content='设计模式内同A'}
修改文档
第二版文档,文档内容:Word{title='java设计模式B', content='设计模式内同B'}
保存第二版文档,文档内容:WordMemento{title='java设计模式B', content='设计模式内同B'}
第三版文档,文档内容:Word{title='java设计模式C', content='设计模式内同C'}
----------------------------------
文档回退,回退后内容:Word{title='java设计模式B', content='设计模式内同B'}
文档再次回退,回退后内容:Word{title='java设计模式A', content='设计模式内同A'}

UML类图