备忘录(Memento)模式的定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后在需要时能将该对象恢复到原先保存的状态。属于行为型模式。
备忘录模式的结构:备忘录模式主要包括以下3个角色。
- 发起人(Originator):记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能。
- 备忘录(Memento):负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人。
- 管理者(Caretaker):对备忘录进行管理,提供保存和获取备忘录的功能,但无法访问与修改备忘录的内容。
备忘录模式的通用实现:
//备忘录
public class Memento {
private String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
}
//发起人
public class Originator {
private String state;
public void setState(String state) {
this.state = state;
}
public String getState() {
return state;
}
public Memento createMemento() {
return new Memento(state);
}
public void restoreMemento(Memento memento) {
this.setState(memento.getState());
}
}
//管理者
public class Caretaker {
private Memento memento;
public void setMemento(Memento memento) {
this.memento = memento;
}
public Memento getMemento() {
return memento;
}
}
//测试类
public class MementoTest {
public static void main(String[] args) {
Originator originator = new Originator();
Caretaker caretaker = new Caretaker();
originator.setState("S0");
System.out.println("初始状态:" + originator.getState());
//备份状态
Memento memento = originator.createMemento();
caretaker.setMemento(memento);
originator.setState("S1");
System.out.println("新的状态:" + originator.getState());
//恢复状态
originator.restoreMemento(caretaker.getMemento());
System.out.println("恢复状态:" + originator.getState());
}
}
备忘录模式的结构图:
备忘录模式的应用实例:公司发布招聘需求后会面试多个候选人,从中挑选最合适的人员录用,我们可以利使用备忘录模式来模拟这一场景。候选人是备忘录,公司是发起人,人才库是管理者。
//候选人(备忘录)
public class Candidate {
private String name;
private Double salary;
public Candidate(String name,Double salary){
this.name = name;
this.salary = salary;
}
public String getName() {
return name;
}
public Double getSalary() {
return salary;
}
}
//发起人
public class Company {
private String employeeName;
private Double salary;
public String getEmployeeName() {
return employeeName;
}
public void setEmployeeName(String employeeName) {
this.employeeName = employeeName;
}
public Double getSalary() {
return salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
public Candidate createMemento() {
System.out.println("候选人"+employeeName+"进入人才库!");
return new Candidate(employeeName,salary);
}
public void restoreMemento(Candidate candidate) {
this.setEmployeeName(candidate.getName());
this.setSalary(candidate.getSalary());
}
}
//管理者
public class TalentPool {
private Map<String,Candidate> candidateMap = new HashMap<>();
public void addCandidate(Candidate candidate) {
candidateMap.put(candidate.getName(),candidate);
}
public Candidate getCandidate(String name) {
return candidateMap.get(name);
}
}
//测试类
public class Test {
public static void main(String[] args) {
Company company = new Company();
TalentPool talentPool = new TalentPool();
//候选人1
company.setEmployeeName("张三");
company.setSalary(15000.00);
Candidate candidate1 = company.createMemento();
talentPool.addCandidate(candidate1);
//候选人2
company.setEmployeeName("李四");
company.setSalary(18000.00);
Candidate candidate2 = company.createMemento();
talentPool.addCandidate(candidate2);
//候选人3
company.setEmployeeName("王五");
company.setSalary(20000.00);
Candidate candidate3 = company.createMemento();
talentPool.addCandidate(candidate3);
//恢复候选人2
company.restoreMemento(talentPool.getCandidate("李四"));
System.out.println("确定录用候选人:"+company.getEmployeeName()+",薪水:"+company.getSalary());
}
}
备忘录模式的优点:
- 提供了状态回滚的机制。当用户需要时能够比较方便地将数据恢复到某个历史的状态。
- 实现了内部状态的封装。除了创建它的发起人之外,其他对象都不能够访问这些状态信息。
- 简化了发起人的职责。发起人不需要管理和保存其内部状态的各个备份,所有状态信息都保存在备忘录中,并由管理者进行管理,这符合单一职责原则。
备忘录模式的缺点是:资源消耗大。如果要保存的内部状态信息过多或者特别频繁,将会占用比较大的内存资源。
备忘录模式的应用场景:
- 需要保存与恢复数据的场景。
- 希望在对象外保存状态,且除了自己其他类无法访问状态保存的具体内容。