定義
在不破壞封裝性的前提下,捕獲一個對象的內(nèi)部狀態(tài),并在該對象之外保存這個狀態(tài)。這樣以后就可以將該對象恢復(fù)到原先保存的狀態(tài)。
結(jié)構(gòu)

備忘錄模式
- Originator(發(fā)起人):負(fù)責(zé)創(chuàng)建一個備忘錄Memento,用以記錄當(dāng)前時刻它的內(nèi)部狀態(tài),并可以使用備忘錄恢復(fù)內(nèi)部狀態(tài)。Originator可根據(jù)需要決定Memento存儲Originator的哪些內(nèi)部狀態(tài)。
- Memetno(備忘錄):負(fù)責(zé)存儲Originator對象的內(nèi)部狀態(tài),并可防止Originator以外的其他對象訪問備忘錄Memento。備忘錄有兩個接口,Caretaker只能看到備忘錄的窄接口,它只能將備忘錄傳遞給其他對象。Originator能夠看到一個寬接口,允許它訪問回到先前狀態(tài)所需的所有數(shù)據(jù)。
- Caretaker(管理者):負(fù)責(zé)保存好備忘錄Memento,不能對備忘錄的內(nèi)容進(jìn)行操作或檢查。
簡單實(shí)現(xiàn)
package memento;
/**
* 發(fā)起人
*/
public class Emp {
private String name;
private int age;
private double salary;
// 進(jìn)行備份操作,返回備忘錄對象
public EmpMemento memento(){
return new EmpMemento(this);
}
// 進(jìn)行恢復(fù)操作
public void recovery(EmpMemento empMemento){
this.name = empMemento.getName();
this.age = empMemento.getAge();
this.salary = empMemento.getSalary();
}
public Emp(String name, int age, double 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 double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
package memento;
/**
* 備忘錄
*/
public class EmpMemento {
private String name;
private int age;
private double salary;
public EmpMemento(Emp e) {
this.name = e.getName();
this.age = e.getAge();
this.salary = e.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 double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
package memento;
/**
* 管理者
*/
public class CareTaker {
private EmpMemento empMemento;
// private List<EmpMemento> list = new ArrayList<EmpMemento>(); // 如果需要存儲多個備份,可以使用集合
public EmpMemento getEmpMemento() {
return empMemento;
}
public void setEmpMemento(EmpMemento empMemento) {
this.empMemento = empMemento;
}
}
package memento;
public class Client {
public static void main(String[] args) {
CareTaker taker = new CareTaker();
Emp emp = new Emp("張三",20,2000);
System.out.println("1.姓名:"+emp.getName()+"; 年齡:"+emp.getAge()+"; 薪水:"+emp.getSalary());
taker.setEmpMemento(emp.memento()); // 備份
emp.setName("李四");
emp.setAge(30);
emp.setSalary(6000);
System.out.println("2.姓名:"+emp.getName()+"; 年齡:"+emp.getAge()+"; 薪水:"+emp.getSalary());
emp.recovery(taker.getEmpMemento()); // 恢復(fù)
System.out.println("3.姓名:"+emp.getName()+"; 年齡:"+emp.getAge()+"; 薪水:"+emp.getSalary());
}
}
輸出:
1.姓名:張三; 年齡:20; 薪水:2000.0
2.姓名:李四; 年齡:30; 薪水:6000.0
3.姓名:張三; 年齡:20; 薪水:2000.0
備忘點(diǎn)較多時
- 將備忘錄壓入棧
- 將多個備忘錄對象,序列化和持久化
小結(jié)
備忘錄模式比較適用于功能比較復(fù)雜的,但需要維護(hù)或記錄屬性歷史的類,或者需要保存的屬性只是眾多屬性中的一小部分時,Originator可以根據(jù)保存的Memento信息還原到前一狀態(tài)。如果在某個系統(tǒng)中使用命令模式時,需要實(shí)現(xiàn)命令的撤銷功能,那么命令模式可以使用備忘錄模式來存儲可撤銷操作的狀態(tài)。