备忘录模式

​ 备忘录模式,即保存某个对象内部状态的拷贝,这样以后就可以将该对象恢复到原先的状态。

场景

​ 当我们使用文本编译器记录一些内容时,发现这一步写错了,往往可以使用Ctrl+Z的方式会退到上一个状态,其中运用到的知识就是备忘录模式。

模式结构

  • 发起者角色(Originator):负责创建一个备忘录用以记录当前时刻它的内部状态,并可以使用备忘录恢复内部状态。
  • 备忘录角色(Memento):负责存储Originator对象的内部状态,并可以防止Originator以外的其他对象访问备忘录。
  • 管理者角色(CareTake):负责保存好备忘录。

代码

备忘录角色

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package designMode.Memento;

/**
* @author YoungDream
* @since 2019/4/21 5:50
*/
public class EmpMemento {
private String name;
private int age;
private int salary;

public EmpMemento(Emp emp) {
this.name = emp.getName();
this.age = emp.getAge();
this.salary = emp.getSalary();
}

//construct、getter和setter等
}

发起者角色

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Emp {
private String name;
private int age;
private int salary;

//进行备份操作,并返回一个备忘录对象
public EmpMemento memento() {
return new EmpMemento(this);
}

//进行数据恢复,恢复成备忘录中的值
public void recovery(EmpMemento empMemento) {
this.name = empMemento.getName();
this.age = empMemento.getAge();
this.salary = empMemento.getSalary();
}

//construct、getter和setter等
}

管理者角色

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 管理者角色:负责管理备忘录类,示例只保存了一个备忘录对象,可以通过设置栈保存多个对象
*
* @author YoungDream
* @since 2019/4/21 6:01
*/
public class CareTaker {
private EmpMemento memento;

public EmpMemento getMemento() {
return memento;
}

public void setMemento(EmpMemento memento) {
this.memento = memento;
}
}

客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Client {
public static void main(String[] args) {
CareTaker careTaker = new CareTaker();

Emp emp = new Emp("YoungDream", 20, 7800);
System.out.println("第一次打印==> " + emp);

careTaker.setMemento(new EmpMemento(emp));//进行备份

emp.setAge(22);
emp.setSalary(8000);
System.out.println("第二次打印==> " + emp);

emp.recovery(careTaker.getMemento());//数据恢复

System.out.println("数据恢复后打印==> " + emp);

}
}

控制台

1
2
3
第一次打印==> Emp{name='YoungDream', age=20, salary=7800}
第二次打印==> Emp{name='YoungDream', age=22, salary=8000}
数据恢复后打印==> Emp{name='YoungDream', age=20, salary=7800}

总结

优点

  • 备忘录模式可以把发起者内部信息对象屏蔽起来,从而可以保持封装的边界。
  • 简化了发起者类。当发起者角色的状态改变的时候,有可能这个状态无效,这时候就可以使用暂时存储起来的备忘录将状态复原。

缺点

  • 如果状态需要完整地存储到备忘录对象中,那么在资源消耗上面备忘录对象比较昂贵。
  • 当发起者对象的状态改变的时候,有可能这个协议无效。如果状态改变的成功率达不到要求,可以考虑采取“假如”协议模式。

当备份点较多时

  • 设置栈将备忘点压栈
  • 将多个备忘录对象持久化和序列化保存到本地

常见场景

  • 数据库事务管理中的回滚操作
  • 文本编辑器中的Ctrl+z回退操作