一、场景
当我们使用文本编译器记录一些内容时,发现这一步写错了,往往可以使用Ctrl+Z的方式会退到上一个状态,其中运用到的知识就是备忘录模式。
二、定义
备忘录模式,即保存某个对象内部状态的拷贝,这样以后就可以将该对象恢复到原先的状态。
三、模式结构
- 发起者角色(Originator):负责创建一个备忘录用以记录当前时刻它的内部状态,并可以使用备忘录恢复内部状态。
- 备忘录角色(Memento):负责存储Originator对象的内部状态,并可以防止Originator以外的其他对象访问备忘录。
- 管理者角色(CareTake):负责保存好备忘录。
代码示例
备忘录角色:
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();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
}
发起者角色:
public class Emp {
private String name;
private int age;
private int salary;
//进行备份操作,并返回一个备忘录对象
public EmpMemento memento(){
return new EmpMemento(this);
}
//进行数据恢复,恢复成备忘录中对象的值
public void recovery(EmpMemento em){
this.name=em.getName();
this.age=em.getAge();
this.salary=em.getSalary();
}
public Emp(String name, int age, int salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
}
管理者角色:
/**
* 管理者角色:负责管理备忘录类,示例只保存了一个备忘录对象,可以通过设置栈保存多个对象
*/
public class CareTaker {
private EmpMemento memento;
public EmpMemento getMemento() {
return memento;
}
public void setMemento(EmpMemento memento) {
this.memento = memento;
}
}
测试类:
public class Client {
public static void main(String[] args) {
CareTaker taker=new CareTaker();
Emp emp=new Emp("张三",18,2000);
System.out.println("第一次打印对象:"+emp.getName()+"----"+emp.getAge()+"---"+emp.getSalary());
taker.setMemento(emp.memento());//进行备忘
emp.setAge(20);
emp.setSalary(3000);
System.out.println("第二次打印对象:"+emp.getName()+"----"+emp.getAge()+"---"+emp.getSalary());
emp.recovery(taker.getMemento());//数据恢复
System.out.println("第三次打印对象:"+emp.getName()+"----"+emp.getAge()+"---"+emp.getSalary());
}
}
输出结果:
四、总结
1、当备忘点较多时
- 设置栈将备忘点压栈
- 将多个备忘录对象持久化和序列化保存到本地
2、优点:
- 备忘录模式可以把发起人内部信息对象屏蔽起来,从而可以保持封装的边界。
- 简化了发起人类。当发起人角色的状态改变的时候,有可能这个状态无效,这时候就可以使用暂时存储起来的备忘录将状态复原。
3、缺点:
- 如果状态需要完整地存储到备忘录对象中,那么在资源消耗上面备忘录对象比较昂贵。
- 当发起者对象的状态改变的时候,有可能这个协议无效。如果状态改变的成功率达不到要求,可以考虑采取“假如”协议模式。
4、开发中的应用场景
- 数据库事务管理中的回滚操作
- 文本编译器中的Ctrl+z回退操作