設計模式21-備忘錄模式

1.場景問題解決

1.1 場景描述

討論一個遊戲進度狀態保存問題
遊戲進度保存:對象狀態,場景…,需要安全性,不能被非保存人讀取到
如果在不使用數據庫的情況下,怎麼設計

1.2 OO設計

保存在數據庫中

1.3 需求變動

1.4 帶來問題

2.用設計模式改進

2.1 分析

[外鏈圖片轉存失敗(img-4IaLCwOf-1568819792579)(https://raw.githubusercontent.com/bobshute/public/master/imgs/csdn/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/21%E5%A4%87%E5%BF%98%E5%BD%95%E6%A8%A1%E5%BC%8F-1.png)]

2.2 重新設計

2.3 源碼

  • MementoIF 接口
  • MementoCaretaker 管理者
public interface MementoIF {
}

public class MementoCaretaker {
	private HashMap<String, MementoIF> mementomap;

	public MementoCaretaker() {
		mementomap = new HashMap<String, MementoIF>();
	}

	//恢復備忘錄
	public MementoIF retrieveMemento(String name) {
		return mementomap.get(name);
	}

	/**
	 * 備忘錄賦值方法-保存備忘錄
	 */
	public void saveMemento(String name, MementoIF memento) {
		this.mementomap.put(name, memento);
	}
}

  • Originator 發起者1,保存數據爲HashMap
  • Originator2 發起者2,保存數據爲ArrayList


public class Originator {
	private HashMap<String, String> state;

	public Originator() {
		state = new HashMap();
	}

	public MementoIF createMemento() {
		return new Memento(state);
	}

	public void restoreMemento(MementoIF memento) {
		state = ((Memento) memento).getState();
	}

	public void showState() {
		System.out.println("now state:" + state.toString());
	}

	public void testState1() {
		state.put("blood", "500");//遊戲中自身血
		state.put("progress", "gate1 end");//遊戲進度
		state.put("enemy", "5");//敵人數目

	}

	public void testState2() {
		state.put("blood", "450");//遊戲中自身血
		state.put("progress", "gate3 start");//遊戲進度
		state.put("enemy", "3");//敵人數目

	}

	private class Memento implements MementoIF {

		private HashMap<String, String> state;

		private Memento(HashMap state) {
			this.state = new HashMap(state);
		}
		private HashMap getState() {
			return state;
		}
		private void setState(HashMap state) {
			this.state = state;
		}
	}
}




public class Originator2 {
	private ArrayList<String> state;

	public Originator2() {
		state = new ArrayList<String>();
	}

	public MementoIF createMemento() {
		return new Memento(state);
	}

	public void restoreMemento(MementoIF memento) {
		state = ((Memento) memento).getState();
	}

	public void testState1() {
		state = new ArrayList<String>();
		state.add("blood:320");
		state.add("progress:gate2 mid");
		state.add("enemy:15");
	}

	public void testState2() {
		state = new ArrayList<String>();
		state.add("blood:230");
		state.add("progress:gate8 last");
		state.add("enemy:12");
	}

	public void showState() {
		System.out.println("now state:" + state.toString());
	}

	private class Memento implements MementoIF {

		private ArrayList<String> state;

		private Memento(ArrayList<String> state) {
			this.state = new ArrayList(state);
		}

		private ArrayList<String> getState() {
			return state;
		}

		private void setState(ArrayList<String> state) {
			this.state = state;
		}
	}

}
  • MementoTest 測試類

public class MementoTest {

	public static void main(String[] args) {
		MementoCaretaker mMementoCaretaker = new MementoCaretaker();
		Originator mOriginator = new Originator();
		Originator2 mOriginator2 = new Originator2();
		
		System.out.println("*****Originator*****");
		mOriginator.testState1();
		mMementoCaretaker
				.saveMemento("Originator", mOriginator.createMemento());
		mOriginator.showState();
		mOriginator.testState2();
		mOriginator.showState();
		mOriginator.restoreMemento(mMementoCaretaker
				.retrieveMemento("Originator"));
		mOriginator.showState();

		System.out.println("*****Originator 2*****");
		mOriginator2.testState1();
		mOriginator2.showState();
		mMementoCaretaker.saveMemento("Originator2",
				mOriginator2.createMemento());
		mOriginator2.testState2();
		mOriginator2.showState();
		mOriginator2.restoreMemento(mMementoCaretaker
				.retrieveMemento("Originator2"));
		mOriginator2.showState();

		//如果保存和恢復不一致則報錯
		//System.out.println("*****Originator&&Originator 2*****");
	//	 mOriginator.restoreMemento(mMementoCaretaker
	//	 .retrieveMemento("Originator2"));
	//	 mOriginator.showState();

	}

}

3.設計模式總結

3.1 定義

備忘錄模式:在不破壞封裝的前提下,存儲關鍵對象的重要狀態,從而可以在將來把對象還原到存儲的那個狀態

3.2 分析思路

21備忘錄模式-2

3.3 優缺點

  • 優點:
    狀態存儲在外面,不和關鍵對象混在一起,這可以幫助維護內聚
    提供了容易實現的恢復能力
    保持了關鍵對象的數據封裝
  • 缺點:
    資源消耗上面備忘錄對象會很昂貴
    存儲和恢復狀態的過程比較耗時

4. 設計模式使用場景及注意

4.1 使用場景

必須保存一個對象在某一個時刻的(整體或部分)狀態,在對象以外的地方, 以後需要時恢復到先前的狀態時

5.參考文章

內容總計於HeadFirst設計模式及相關視頻

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章