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 分析思路
3.3 優缺點
- 優點:
狀態存儲在外面,不和關鍵對象混在一起,這可以幫助維護內聚
提供了容易實現的恢復能力
保持了關鍵對象的數據封裝 - 缺點:
資源消耗上面備忘錄對象會很昂貴
存儲和恢復狀態的過程比較耗時
4. 設計模式使用場景及注意
4.1 使用場景
必須保存一個對象在某一個時刻的(整體或部分)狀態,在對象以外的地方, 以後需要時恢復到先前的狀態時
5.參考文章
內容總計於HeadFirst設計模式及相關視頻