玩游戲的時(shí)候,會(huì)有關(guān)卡以及boss,通過(guò)boss戰(zhàn)后,獲得新裝備,新開(kāi)啟關(guān)卡,并會(huì)提示存儲(chǔ)當(dāng)前進(jìn)度,以便以后可以再重玩當(dāng)前boss戰(zhàn),比如生化危機(jī),鬼泣等等殺完一個(gè)boss爽了,然后存儲(chǔ)下當(dāng)前進(jìn)度,但是這種存儲(chǔ)都是需要介質(zhì)持久化,如果需要在內(nèi)存中長(zhǎng)久駐留,那么就要采用一些方式存儲(chǔ)。
當(dāng)玩家創(chuàng)建一個(gè)角色的時(shí)候,與該角色相關(guān)的東西都會(huì)附加上,比如裝備,角色外貌,場(chǎng)景等等,這些東西封裝為一個(gè)對(duì)象,然后將對(duì)象狀態(tài)保存在外部,就是備忘錄模式了,下面為第一版簡(jiǎn)略類(lèi)圖:展模式.jpg)
Roll是角色,RollState是角色附加的東西:裝備,場(chǎng)景,殺了幾個(gè)boss,獲得的新裝備等等也就是當(dāng)前角色的狀態(tài),GameState是用來(lái)存儲(chǔ)角色狀態(tài)的類(lèi),GameStateManager是角色狀態(tài)管理類(lèi),但是這種方式,只能針對(duì)不同角色存儲(chǔ)一種狀態(tài)的情況,
比如鬼泣主角:但丁 當(dāng)?shù)谝魂P(guān)通過(guò)后,獲得新裝備,新關(guān)卡,此時(shí)存儲(chǔ)下來(lái),即GameStateManager.setGameState()方法,內(nèi)部用map存儲(chǔ)即manager.put("但丁",gameState),但是用map只能存儲(chǔ)但丁的一個(gè)狀態(tài),如果再有另外一個(gè)角色:惡魔但丁,同樣會(huì)只能存儲(chǔ)一個(gè)狀態(tài),上面類(lèi)圖只針對(duì)不同角色,當(dāng)前狀態(tài),以及上一個(gè)狀態(tài)之間的切換。如果一個(gè)角色有多個(gè)狀態(tài),狀態(tài)之間跳躍,比如打完第6關(guān),玩家想切換回第3關(guān)玩,如果遇見(jiàn)這種情況,那么將GameStateManager的map泛型第二個(gè)參數(shù)改為聚集即可。第二版類(lèi)圖如下:
:
GameStateManager成員變量第二個(gè)泛型參數(shù)改為Collection<GameState>,里面參數(shù)即可根據(jù)角色名字和第幾個(gè)關(guān)卡獲取狀態(tài),代碼如
package designpattern.memento;

public class Roll


{
private RollState rollState = new RollState("默認(rèn)裝備", "默認(rèn)樣子", "出生場(chǎng)景");

private String name;

public Roll(String name)

{
this.name = name;
}

public void killBossA()

{
System.out.println("殺了boss1,獲得新裝備,開(kāi)啟關(guān)卡2");
rollState.setEquipment("新裝備");
rollState.setAppearance( "獲得新外型");
rollState.setScene("開(kāi)啟關(guān)卡2");
}

public void killBossB()

{
System.out.println( "殺了boss2,獲得更好的裝備,開(kāi)啟更難關(guān)卡");
rollState.setEquipment( "更強(qiáng)裝備");
rollState.setAppearance( "獲得更酷外型");
rollState.setScene(name + "開(kāi)啟關(guān)卡3");
}

public RollState getRollState()

{
return rollState;
}

public void setRollState(RollState rollState)

{
this.rollState = rollState;
}

public String getName()

{
return name;
}

public void setName(String name)

{
this.name = name;
}


/** *//**
* 創(chuàng)建備份點(diǎn)
*
* @return
*/
public GameState createGameState()

{
return new GameState(rollState);
}


/** *//**
* 獲得上次備份點(diǎn)
*
* @param gameState
*/
public void restoreGameState(GameState gameState)

{
this.rollState = gameState.getRollState();
}

@Override
public String toString()

{
return name+":"+this.getRollState().getEquipment()+", "+this.getRollState().getAppearance()+", "+this.getRollState().getScene();
}
}

package designpattern.memento;


/** *//**
* @author Administrator 角色狀態(tài)類(lèi)
*/
public class RollState


{

private String equipment;
private String appearance;
private String scene;

public RollState()

{
}

public RollState(String equipment, String appearance, String scene)

{
this.equipment = equipment;
this.appearance = appearance;
this.scene = scene;
}

public String getEquipment()

{
return equipment;
}

public void setEquipment(String equipment)

{
this.equipment = equipment;
}

public String getAppearance()

{
return appearance;
}

public void setAppearance(String appearance)

{
this.appearance = appearance;
}

public String getScene()

{
return scene;
}

public void setScene(String scene)

{
this.scene = scene;
}

}

package designpattern.memento;

public class GameState


{
private RollState rollState;

public GameState(RollState rollState)

{
this.rollState = rollState;
}

public RollState getRollState()

{
return rollState;
}

public void setRollState(RollState rollState)

{
this.rollState = rollState;
}

}

package designpattern.memento;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class GameStateManager


{
private Map<String, ArrayList<GameState>> managers = new HashMap<String,ArrayList<GameState>>();

public GameState getGameState(String rollName, int indexBoss)

{
return managers.get(rollName).get(indexBoss);
}

public void setGameState(String rollName, GameState gameState)

{
ArrayList<GameState> list = null;
if ((list = managers.get(rollName)) != null)

{
list.add(gameState);
} else

{
managers.put(rollName,new ArrayList<GameState>(Arrays.asList(gameState)));
}
System.err.println(managers.get(rollName));
}
}

package designpattern.memento;

public class Client


{
public static void main(String[] args)

{
Roll roll = new Roll( "但丁");
GameStateManager states = new GameStateManager();
//玩家初始場(chǎng)景,即出生點(diǎn)
states.setGameState(roll.getName(), roll.createGameState());
roll.killBossA();
//殺完bossA 存儲(chǔ)
states.setGameState(roll.getName(), roll.createGameState());
roll.killBossB();
//殺完bossB存儲(chǔ)
states.setGameState(roll.getName(), roll.createGameState());
//玩家想返回殺bossA之前場(chǎng)景 內(nèi)部使用線性表存儲(chǔ) 0即代表玩家出生點(diǎn),初始場(chǎng)景,一般游戲里面會(huì)對(duì)每個(gè)boss戰(zhàn)場(chǎng)景標(biāo)記
roll.restoreGameState(states.getGameState(roll.getName(), 0));
System.out.println(roll.toString());
roll.restoreGameState(states.getGameState(roll.getName(), 1));
System.out.println(roll.toString());
}
}

這跟事物原理一致
上面有個(gè)bug,Roll類(lèi)里面killBossA方法應(yīng)該改為:
// rollState.setEquipment("新裝備A");
// rollState.setAppearance("獲得新外型A");
// rollState.setScene("開(kāi)啟關(guān)卡2");
rollState = new RollState("新裝備A","獲得新外型A","開(kāi)啟關(guān)卡2");
killBossB方法應(yīng)該改為:
rollState = new RollState("更強(qiáng)裝備B","獲得更酷外型B","開(kāi)啟關(guān)卡3");
// rollState.setEquipment("更強(qiáng)裝備B");
// rollState.setAppearance("獲得更酷外型B");
// rollState.setScene(name + "開(kāi)啟關(guān)卡3");
否則都傳遞的是引用,修改的是同一個(gè)引用,保存的都是同一個(gè)狀態(tài)。
因?yàn)閞oll角色的狀態(tài)是通過(guò)RollState引用來(lái)保存,而不是基本變量和string類(lèi)型