設計模式學習筆記——備忘錄模式

備忘錄模式

備忘錄模式,在不破壞封裝性的前提下,捕獲一個對象的內部狀態,並在該對象之外保存這個狀態。這樣以後就可以將該對象恢復到原先保存的狀態。

結構圖


代碼實現

備忘錄類Memento:
/**
 * 備忘錄:負責儲存原始對象的內部狀態
 * @author xukai
 * 2016年3月23日 下午6:44:26
 */
public class Memento {

	private String state;
	
	public Memento(String state) {
		this.state = state;
	}

	public String getState() {
		return state;
	}

	public void setState(String state) {
		this.state = state;
	}
	
}
需要保存狀態的對象:
/**
 * 保存對象:負責創建備忘錄
 * @author xukai
 * 2016年3月23日 下午6:44:07
 */
public class Originator {

	private String state;

	public String getState() {
		return state;
	}

	public void setState(String state) {
		this.state = state;
	}

	public Memento createMemento(){
		return new Memento(state);
	}
	
	public void setMemento(Memento memento){
		state = memento.getState();
	}
	
	public void show(){
		System.out.println("state=" + state);
	}
	
}
管理者:執行保存備忘錄操作
/**
 * 管理者:保存備忘錄
 * @author xukai
 * 2016年3月23日 下午10:55:32
 */
public class Caretaker {

	private Memento memento;

	/**
	 * @return
	 */
	public Memento getMemento() {
		return memento;
	}

	public void setMemento(Memento memento) {
		this.memento = memento;
	}
	
}
客戶端:
public class Client {

	public static void main(String[] args) {
		Originator o = new Originator();
		o.setState("on");
		o.show();
		
		Caretaker c = new Caretaker();
		c.setMemento(o.createMemento());
		
		o.setState("off");
		o.show();
		o.setMemento(c.getMemento());
		o.show();
	}
	
}
Console:
state=on
state=off
state=on
首先,創建一個初識對象,賦給其某種狀態。
其次,使用管理者,執行保存備忘錄操作,記錄當前原始對象的狀態。
接着,原始對象的狀態由於某種原因發生改變,但是需要將狀態恢復到保存備忘錄的狀態。
最後,原始對象通過管理者中的備忘錄,獲取保存的狀態。

demo

問題:使用小霸王遊戲機在打大BOSS之前一般都有存檔,Game Over之後,可以回到存檔位置,重新打BOSS。

結構圖


代碼實現

角色狀態存儲:
/**
 * 角色備忘錄:角色狀態存儲
 * @author xukai
 * 2016年3月23日 下午11:17:56
 */
public class RoleStateMemento {

	private int vit;	// 生命力
	
	private int atk;	// 攻擊力
	
	private int def;	// 防禦力

	public RoleStateMemento(int vit, int atk, int def) {
		this.vit = vit;
		this.atk = atk;
		this.def = def;
	}

	public int getVit() {
		return vit;
	}

	public void setVit(int vit) {
		this.vit = vit;
	}

	public int getAtk() {
		return atk;
	}

	public void setAtk(int atk) {
		this.atk = atk;
	}

	public int getDef() {
		return def;
	}

	public void setDef(int def) {
		this.def = def;
	}
	
}
遊戲角色:
/**
 * 遊戲角色
 * @author xukai
 * 2016年3月23日 下午11:19:37
 */
public class GameCharacters {

	private int vit;	// 生命力
	
	private int atk;	// 攻擊力
	
	private int def;	// 防禦力
	
	// 初始化
	public void init(){
		this.vit = 100;
		this.atk = 100;
		this.def = 100;
	}
	
	// 大戰之後
	public void fight(){
		this.vit = 0;
		this.atk = 0;
		this.def = 0;
	}
	
	public RoleStateMemento saveState(){
		return new RoleStateMemento(vit, atk ,def);
	}
	
	public void recoveryState(RoleStateMemento roleStateMemento){
		this.vit = roleStateMemento.getVit();
		this.atk = roleStateMemento.getAtk();
		this.def = roleStateMemento.getDef();
	}

	@Override
	public String toString() {
		return "GameCharacters [vit=" + vit + ", atk=" + atk + ", def=" + def + "]";
	}
	
}
管理員:
/**
 * 管理員
 * 
 * @author xukai 2016年3月23日 下午11:23:14
 */
public class RoleStateCaretaker {

	private RoleStateMemento memento;

	public RoleStateMemento getMemento() {
		return memento;
	}

	public void setMemento(RoleStateMemento memento) {
		this.memento = memento;
	}

}
客戶端測試:
public class Client {

	public static void main(String[] args) {
		// 準備打BOSS
		GameCharacters characters = new GameCharacters();
		characters.init();
		System.out.println(characters);
		
		// 保存進度
		RoleStateCaretaker caretaker = new RoleStateCaretaker();
		caretaker.setMemento(characters.saveState());
		
		// 打BOSS失敗
		characters.fight();
		System.out.println(characters);
		
		//重新開始,讀存檔
		characters.recoveryState(caretaker.getMemento());
		System.out.println(characters);
	}
	
}
Console:
GameCharacters [vit=100, atk=100, def=100]
GameCharacters [vit=0, atk=0, def=0]
GameCharacters [vit=100, atk=100, def=100]

總結

Memento模式適用於比較複雜的、但需要維護或記錄屬性歷史的類。或者需要保存的屬性只是一小部分,Originator可以通過這些小部分信息還原到上一狀態。
另外,適用備忘錄可以將複雜對象的內部信息對其他對象屏蔽。
當角色的狀態改變的時候,有可能這個狀態無效,那麼就可以使用備忘錄暫時存儲起來,方便狀態復原。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章