文章目录
  1. 1. 备忘录模式
    1. 1.1. 介绍
      1. 1.1.1. 意图
      2. 1.1.2. 主要解决
      3. 1.1.3. 何时使用
      4. 1.1.4. 如何解决
      5. 1.1.5. 关键代码
      6. 1.1.6. 应用实例
      7. 1.1.7. 优点
      8. 1.1.8. 缺点
      9. 1.1.9. 使用场景
      10. 1.1.10. 注意事项
    2. 1.2. 模式结构
    3. 1.3. 实现
      1. 1.3.1. 步骤 1
      2. 1.3.2. 步骤 2
      3. 1.3.3. 步骤 3
      4. 1.3.4. 步骤 4

备忘录模式

备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。

介绍

意图

在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。

主要解决

所谓备忘录模式就是在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。

何时使用

很多时候我们总是需要记录一个对象的内部状态,这样做的目的就是为了允许用户取消不确定或者错误的操作,能够恢复到他原先的状态,使得他有”后悔药”可吃。

如何解决

通过一个备忘录类专门存储对象状态。

关键代码

客户不与备忘录类耦合,与备忘录管理类耦合。

应用实例

  1. 后悔药
  2. 打游戏时的存档
  3. Windows 里的 ctri + z
  4. IE 中的后退
  5. 数据库的事务管理

优点

  1. 给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。
  2. 实现了信息的封装,使得用户不需要关心状态的保存细节。

缺点

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

使用场景

  1. 需要保存/恢复数据的相关状态场景。
  2. 提供一个可回滚的操作。

注意事项

  1. 为了符合迪米特原则,还要增加一个管理备忘录的类。
  2. 为了节约内存,可使用原型模式+备忘录模式。

模式结构

下图是备忘录模式的UML结构图:

在备忘录模式结构图中包含如下几个角色:

  • Originator(原发器):它是一个普通类,可以创建一个备忘录,并存储它的当前内部状态,也可以使用备忘录来恢复其内部状态,一般将需要保存内部状态的类设计为原发器。
  • Memento(备忘录):存储原发器的内部状态,根据原发器来决定保存哪些内部状态。备忘录的设计一般可以参考原发器的设计,根据实际需要确定备忘录类中的属性。需要注意的是,除了原发器本身与负责人类之外,备忘录对象不能直接供其他类使用,原发器的设计在不同的编程语言中实现机制会有所不同。
  • Caretaker(负责人):负责人又称为管理者,它负责保存备忘录,但是不能对备忘录的内容进行操作或检查。在负责人类中可以存储一个或多个备忘录对象,它只负责存储对象,而不能修改对象,也无须知道对象的实现细节。

理解备忘录模式并不难,但关键在于如何设计备忘录类和负责人类。由于在备忘录中存储的是原发器的中间状态,因此需要防止原发器以外的其他对象访问备忘录,特别是不允许其他对象来修改备忘录。

实现

备忘录模式使用三个类 Memento、Originator 和 CareTaker。Memento 包含了要被恢复的对象的状态。Originator 创建并在 Memento 对象中存储状态。Caretaker 对象负责从 Memento 中恢复对象的状态。
MementoPatternDemo,我们的演示类使用 CareTaker 和 Originator 对象来显示对象的状态恢复。

步骤 1

创建 Memento 类。
Memento.java

1
2
3
4
5
6
7
8
9
10
11
public class Memento {
private String state;

public Memento(String state){
this.state = state;
}

public String getState(){
return state;
}
}

步骤 2

创建 Originator 类。
Originator.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Originator {
private String state;

public void setState(String state){
this.state = state;
}

public String getState(){
return state;
}

public Memento saveStateToMemento(){
return new Memento(state);
}

public void getStateFromMemento(Memento Memento){
state = Memento.getState();
}
}

步骤 3

创建 CareTaker 类。
CareTaker.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import java.util.ArrayList;
import java.util.List;

public class CareTaker {
private List<Memento> mementoList = new ArrayList<Memento>();

public void add(Memento state){
mementoList.add(state);
}

public Memento get(int index){
return mementoList.get(index);
}
}

步骤 4

使用 CareTaker 和 Originator 对象。
MementoPatternDemo.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class MementoPatternDemo {
public static void main(String[] args) {
Originator originator = new Originator();
CareTaker careTaker = new CareTaker();
originator.setState("State #1");
originator.setState("State #2");
careTaker.add(originator.saveStateToMemento());
originator.setState("State #3");
careTaker.add(originator.saveStateToMemento());
originator.setState("State #4");

System.out.println("Current State: " + originator.getState());
originator.getStateFromMemento(careTaker.get(0));
System.out.println("First saved State: " + originator.getState());
originator.getStateFromMemento(careTaker.get(1));
System.out.println("Second saved State: " + originator.getState());
}
}

步骤 5
验证输出。

1
2
3
Current State: State #4
First saved State: State #2
Second saved State: State #3


参考资料:

  1. 菜鸟教程
  2. quanke.gitbooks.io
文章目录
  1. 1. 备忘录模式
    1. 1.1. 介绍
      1. 1.1.1. 意图
      2. 1.1.2. 主要解决
      3. 1.1.3. 何时使用
      4. 1.1.4. 如何解决
      5. 1.1.5. 关键代码
      6. 1.1.6. 应用实例
      7. 1.1.7. 优点
      8. 1.1.8. 缺点
      9. 1.1.9. 使用场景
      10. 1.1.10. 注意事项
    2. 1.2. 模式结构
    3. 1.3. 实现
      1. 1.3.1. 步骤 1
      2. 1.3.2. 步骤 2
      3. 1.3.3. 步骤 3
      4. 1.3.4. 步骤 4