設計模式-備忘錄模式 本質:保存和恢復對象狀態(部分狀態) 不破壞封裝性的前提下,獲取一個對象的內部狀態,並在該對象外保存這個狀態。 Memento模式比較適用於功能比較複雜的,但需要維護或記錄屬性歷史的類,或者保護的屬性只是衆多屬性中的一小部分。 典型例子: 遊戲大戰Boss前會保存記錄。
UML圖:
下面用一個30歲的中年人想穿越回10歲小孩的例子來模擬下這個備忘錄模式。
先來個Person類:
Person有基本的年齡和力量屬性,這個 穿越時,會變化,但是記憶是不會變化的,如果記憶也變化了,那麼就不是穿越了,哈哈。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Person {
private int age;//年齡
private int power;//力量
private List<String> rememberList = new ArrayList<>();//記憶 這個屬性是不用寫進備忘錄的,即使穿越了也會有的
public void show(){
System.out.println("age:"+age+" power:"+power+" remember:"+ Arrays.toString(rememberList.toArray()));
System.out.println();
}
/**
* 記錄此時此刻
*/
public PersonMemento record(){
PersonMemento personMemento = new PersonMemento();
personMemento.setAge(this.getAge());
personMemento.setPower(this.getPower());
return personMemento;
}
/**
* 重新來一次
* @param personMemento
*/
public void reback(PersonMemento personMemento){
this.age = personMemento.getAge();
this.power = personMemento.getPower();
}
//getter and setter
}
備忘錄類:
這個類的屬性是Person的部分屬性,用來保存當時的狀態。
問:可以直接用Person類嗎?
答:如果大部門屬性都一樣,是可以的,這時可以用原型模式進行復制。但是如果類屬性特別多,但是需要備忘的數據特別少,那麼就建議使用備忘錄類。
/**
* 人物備忘錄
*/
public class PersonMemento {
private int age;
private int power;
//getter and setter
}
備忘錄管理者類:
備忘錄 管理者,主要就是 對 備忘錄的 存和拿。
/**
* 時間之神 備忘錄管理者
*/
public class TimeGod {
private PersonMemento personMemento;
//getter and setter
public PersonMemento getPersonMemento() {
return personMemento;
}
public void setPersonMemento(PersonMemento personMemento) {
this.personMemento = personMemento;
}
}
調用者(測試類):
public class Test {
public static void main(String[] args) {
TimeGod timeGod = new TimeGod();//時間之神,備忘錄管理者
System.out.println("10歲 主人公出場了");
Person person = new Person();
//年齡10歲 能力15
person.setAge(10);
person.setPower(15);
person.getRememberList().add("那年我10歲,但是能力只有15,不能自己買棒棒糖給自己。\n");
System.out.print("現在狀態:" );
person.show();
//
System.out.println("時間之神默默記錄下了當時的情況");
timeGod.setPersonMemento(person.record());
System.out.println("主人公長大了");
person.setAge(30);
person.setPower(200);
person.getRememberList().add("現在我已經30歲了,有很大的能力是,可以買很多棒棒糖了。\n");
System.out.print("現在狀態:" );
person.show();
System.out.println("他向時間之神許了個願望,想回到10歲,時間之神答應了");
person.reback(timeGod.getPersonMemento());
System.out.println("回到過去...");
System.out.print("現在狀態:" );
person.show();
}
}
測試輸出結果:
10歲 主人公出場了
現在狀態:age:10 power:15 remember:[那年我10歲,但是能力只有15,不能自己買棒棒糖給自己。
]
時間之神默默記錄下了當時的情況
主人公長大了
現在狀態:age:30 power:200 remember:[那年我10歲,但是能力只有15,不能自己買棒棒糖給自己。
, 現在我已經30歲了,有很大的能力是,可以買很多棒棒糖了。
]
他向時間之神許了個願望,想回到10歲,時間之神答應了
回到過去...
現在狀態:age:10 power:15 remember:[那年我10歲,但是能力只有15,不能自己買棒棒糖給自己。
, 現在我已經30歲了,有很大的能力是,可以買很多棒棒糖了。
]
優化:
上面的例子備忘錄只有一個,可以做成多個,在關鍵節點都進行狀態保存。
上訴說到原型模式,如果你還對此模式不是很瞭解,可以查閱筆者的博客: