遊戲角色狀态恢複問題
遊戲角色有攻擊力和防禦力,在大戰Boss 前儲存自身的狀态(攻擊力和防禦力),當大戰Boss 後攻擊力和防禦力下降,從備忘錄對象恢複到大戰前的狀态
傳統方案解決遊戲角色恢複
傳統的方式的問題分析
- 一個對象,就對應一個儲存對象狀态的對象, 這樣當我們遊戲的對象很多時,不利于管理,開銷也很大.
- 傳統的方式是簡單地做備份,new 出另外一個對象出來,再把需要備份的資料放到這個新對象,但這就暴露了對象内部的細節
- 解決方案: => 備忘錄模式
備忘錄模式基本介紹
基本介紹
- 備忘錄模式(Memento Pattern)在不破壞封裝性的前提下,捕獲一個對象的内部狀态,并在該對象之外儲存這個狀态。這樣以後就可将該對象恢複到原先儲存的狀态
- 可以這裡了解備忘錄模式:現實生活中的備忘錄是用來記錄某些要去做的事情,或者是記錄已經達成的共同意見的事情,以防忘記了。而在軟體層面,備忘錄模式有着相同的含義,備忘錄對象主要用來記錄一個對象的某種狀态,或者某些資料,當要做回退時,可以從備忘錄對象裡擷取原來的資料進行恢複操作
- 備忘錄模式屬于行為型模式
備忘錄模式的原理類圖
- 對原理類圖的說明-即(備忘錄模式的角色及職責)
- originator : 對象(需要儲存狀态的對象)
- Memento : 備忘錄對象,負責儲存好記錄,即Originator 内部狀态
- Caretaker: 守護者對象,負責儲存多個備忘錄對象, 使用集合管理,提高效率
- 說明:如果希望儲存多個originator 對象的不同時間的狀态,也可以,隻需要要HashMap <String, 集合>
儲存:需要儲存狀态的對象建立備忘錄對象,再把備忘錄對象儲存到守護者對象,
讀取,從守護者對象讀取備忘錄對象,錄入需要儲存狀态的對象
代碼實作
略
遊戲角色恢複狀态執行個體
-
應用執行個體要求
遊戲角色有攻擊力和防禦力,在大戰Boss 前儲存自身的狀态(攻擊力和防禦力),當大戰Boss 後攻擊力和防禦力下降,從備忘錄對象恢複到大戰前的狀态
- 思路分析和圖解(類圖) Gamerole裡面有Memeto
- 代碼實作
用戶端
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
//建立遊戲角色
GameRole gameRole = new GameRole();
gameRole.setVit(100);
gameRole.setDef(100);
System.out.println("和boss大戰前的狀态");
gameRole.display();
//把目前狀态儲存caretaker
Caretaker caretaker = new Caretaker();
caretaker.setMemento(gameRole.createMemento());
System.out.println("和boss大戰~~~");
gameRole.setDef(30);
gameRole.setVit(30);
gameRole.display();
System.out.println("大戰後,使用備忘錄對象恢複到站前");
gameRole.recoverGameRoleFromMemento(caretaker.getMemento());
System.out.println("恢複後的狀态");
gameRole.display();
}
}
需要儲存狀态的對象:
public class GameRole {
private int vit;
private int def;
//建立Memento ,即根據目前的狀态得到Memento
public Memento createMemento() {
return new Memento(vit, def);
}
//從備忘錄對象,恢複GameRole的狀态
public void recoverGameRoleFromMemento(Memento memento) {
this.vit = memento.getVit();
this.def = memento.getDef();
}
//顯示目前遊戲角色的狀态
public void display() {
System.out.println("遊戲角色目前的攻擊力:" + this.vit + " 防禦力: " + this.def);
}
public int getVit() {
return vit;
}
public void setVit(int vit) {
this.vit = vit;
}
public int getDef() {
return def;
}
public void setDef(int def) {
this.def = def;
}
}
備忘錄對象,負責儲存好記錄
public class Memento {
//攻擊力
private int vit;
//防禦力
private int def;
public Memento(int vit, int def) {
super();
this.vit = vit;
this.def = def;
}
public int getVit() {
return vit;
}
public void setVit(int vit) {
this.vit = vit;
}
public int getDef() {
return def;
}
public void setDef(int def) {
this.def = def;
}
}
守護者對象,負責儲存多個備忘錄對象
import java.util.ArrayList;
import java.util.HashMap;
//守護者對象, 儲存遊戲角色的狀态
public class Caretaker {
//如果隻儲存一次狀态
private Memento memento;
//對GameRole 儲存多次狀态
//private ArrayList<Memento> mementos;
//對多個遊戲角色儲存多個狀态
//private HashMap<String, ArrayList<Memento>> rolesMementos;
public Memento getMemento() {
return memento;
}
public void setMemento(Memento memento) {
this.memento = memento;
}
}
備忘錄模式的注意事項和細節
- 給使用者提供了一種可以恢複狀态的機制,可以使使用者能夠比較友善地回到某個曆史的狀态
- 實作了資訊的封裝,使得使用者不需要關心狀态的儲存細節
- 如果類的成員變量過多,勢必會占用比較大的資源,而且每一次儲存都會消耗一定的記憶體, 這個需要注意
- 适用的應用場景:1、後悔藥。2、打遊戲時的存檔。3、Windows 裡的ctri + z。4、IE 中的後退。4、資料庫的事務管理
- 為了節約記憶體,備忘錄模式可以和原型模式配合使用
總結
看 備忘錄模式的原理類圖