什么是备忘录模式?
备忘录模式(Memento Pattern)又叫做快照模式(Snapshot Pattern)或Token模式,是GoF的23种设计模式之一,属于行为模式。
定义:在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
涉及角色
1. Originator源发器类(发起人):负责创建一个备忘录Memento,用以记录当前时刻自身的内部状态,并可使用备忘录恢复内部状态。Originator可以根据需要决定Memento存储自己的哪些内部状态。
2. Memento备忘录类(备忘录):负责存储Originator对象的内部状态,并可以防止Originator以外的其他对象访问备忘录。备忘录有两个接口:Caretaker只能看到备忘录的窄接口,他只能将备忘录传递给其他对象。Originator却可看到备忘录的宽接口,允许它访问返回到先前状态所需要的所有数据。
3. Caretaker负责人类(管理者):负责保存好备忘录Memento,不能对Memento的内容进行访问或者操作。可以通过增加容器,设置多个备忘点。
场景
- 录入大批人员资料。正在录入当前人资料时,发现上一个人录错了,此时需要恢复上一个人的资料,在进行修改。
- Word文档编辑时,忽然电脑死机或断电,在打开是,可以看到word提示你恢复到以前的文档。
- 管理系统中,公文撤回功能。发送出去后,想撤回来。
- 棋类游戏中的,悔棋。
- 普通软件中的,撤销操作。
- 数据库软件中,事务管理的回滚操作。
- PhotoShop软件中的,历史记录。
举例
雇员信息的修改及恢复。
类图
代码
Originator源发器类(发起人):
package com.match.memento;
/**
* Originator源发器类(发起人)
* @author Match
*
*/
public class Emp
{
private String ename;
private int age;
private double salary;
//进行备忘操作,并返回备忘录对象
public EmpMemento memento()
{
return new EmpMemento(this);
}
//进行数据恢复,恢复成制定备忘录对象的值
public void recovery(EmpMemento mmt)
{
this.ename=mmt.getEname();
this.age=mmt.getAge();
this.salary=mmt.getSalary();
}
public Emp(String ename, int age, double salary)
{
super();
this.ename = ename;
this.age = age;
this.salary = salary;
}
public String getEname()
{
return ename;
}
public void setEname(String ename)
{
this.ename = ename;
}
public int getAge()
{
return age;
}
public void setAge(int age)
{
this.age = age;
}
public double getSalary()
{
return salary;
}
public void setSalary(double salary)
{
this.salary = salary;
}
}
Memento备忘录类(备忘录):
package com.match.memento;
/**
* Memento备忘录类(备忘录)
* @author Match
*
*/
public class EmpMemento
{
private String ename;
private int age;
private double salary;
public EmpMemento(Emp e)
{
this.ename=e.getEname();
this.age=e.getAge();
this.salary= e.getSalary();
}
public String getEname()
{
return ename;
}
public void setEname(String ename)
{
this.ename = ename;
}
public int getAge()
{
return age;
}
public void setAge(int age)
{
this.age = age;
}
public double getSalary()
{
return salary;
}
public void setSalary(double salary)
{
this.salary = salary;
}
}
Caretaker负责人类(管理者):
package com.match.memento;
/**
* Caretaker负责人类(管理者)
* 负责管理备忘录对象
* @author Match
*
*/
public class CareTaker
{
private EmpMemento memento;
// private List<EmpMemento> list = new ArrayList<EmpMemento>();
public EmpMemento getMemento()
{
return memento;
}
public void setMemento(EmpMemento memento)
{
this.memento = memento;
}
}
客户端:
package com.match.memento;
public class Client
{
public static void main(String[] args)
{
CareTaker taker = new CareTaker();
Emp emp = new Emp("Match",18,1000000);
System.out.println("原雇员信息:"+emp.getEname()+"---"+emp.getAge()+"---"+emp.getSalary());
System.out.println("***************备忘原雇员信息***************");
taker.setMemento(emp.memento());//备忘一次
System.out.println("***************修改原雇员信息***************");
emp.setEname("Bob");
emp.setAge(20);
emp.setSalary(100000);
System.out.println("修改后的雇员信息:"+emp.getEname()+"---"+emp.getAge()+"---"+emp.getSalary());
System.out.println("***************恢复为原有雇员信息************");
emp.recovery(taker.getMemento());
System.out.println("恢复后的雇员信息:"+emp.getEname()+"---"+emp.getAge()+"---"+emp.getSalary());
}
}
测试输出:
原雇员信息:Match---18---1000000.0
***************备忘原雇员信息***************
***************修改原雇员信息***************
修改后的雇员信息:Bob---20---100000.0
***************恢复为原有雇员信息************
恢复后的雇员信息:Match---18---1000000.0