备忘录模式(Token)
一、定义
在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
二、适用场景
适合于功能比较复杂,但需要维护或记录属性历史的功能。
参与者:
Originator(发起人):负责创建一个备忘录Memento,用以记录当前时刻自身的内部状态,并可使用备忘录恢复内部状态。Originator可以根据需要决定Memento存储自己的哪些内部状态。
Memento(备忘录):负责存储Originator对象的内部状态,并可以防止Originator以外的其他对象访问备忘录。备忘录有两个接口:Caretaker只能看到备忘录的窄接口,他只能将备忘录传递给其他对象。Originator却可看到备忘录的宽接口,允许它访问返回到先前状态所需要的所有数据。
Caretaker(管理者):负责备忘录Memento,不能对Memento的内容进行访问或者操作。
适用性:
1)必须保存一个对象在某一时刻的(部分)状态,这样以后需要时它才能恢复到先前的状态。
2)如果一个用接口来让其它对象直接得到这些状态,将会暴露对象的实现细节并破坏对象的封装性。
效果:
1)保持封装边界
2)简化原发器
3)使用备忘录可能代价很高
4)定义窄接口和宽接口
5)维护备忘录的潜在代价
三、UML

四、代码
-
/**
-
* 游戏自身(备忘录模式中的发起人,备份的是游戏的状态)
-
*/
-
public class Game {
-
-
/**
-
* 英雄状态属性
-
*/
-
private HeroState hState;
-
-
/**
-
* 场景状态属性
-
*/
-
private SceneState sState;
-
-
public HeroState gethState() {
-
return hState;
-
}
-
-
public void sethState(HeroState hState) {
-
this.hState = hState;
-
}
-
-
public SceneState getsState() {
-
return sState;
-
}
-
-
public void setsState(SceneState sState) {
-
this.sState = sState;
-
}
-
-
/**
-
* 备份游戏
-
*/
-
public GameMemento createMemento(){
-
return new GameMemento(hState,sState);
-
}
-
-
/**
-
* 玩游戏
-
* @throws InterruptedException
-
*/
-
public void play(){
-
hState.setHP(0);
-
hState.setMP(0);
-
sState.setCoin(0);
-
sState.setWood(0);
-
}
-
-
/**
-
* 游戏还原
-
*/
-
public void restore(GameMemento memento){
-
this.hState = memento.gethState();
-
this.sState = memento.getsState();
-
}
- }
点击(此处)折叠或打开
-
/**
-
* 游戏英雄人物状态实体
-
*/
-
public class HeroState implements Cloneable{
-
-
/**
-
* 英雄生命值
-
*/
-
private int HP;
-
-
/**
-
* 英雄魔法值
-
*/
-
private int MP;
-
-
/**
-
* 状态保存时间
-
*/
-
private Date stateDate;
-
-
public int getHP() {
-
return HP;
-
}
-
-
public void setHP(int hP) {
-
HP = hP;
-
}
-
-
public int getMP() {
-
return MP;
-
}
-
-
public void setMP(int mP) {
-
MP = mP;
-
}
-
-
public Date getStateDate() {
-
return stateDate;
-
}
-
-
public void setStateDate(Date stateDate) {
-
this.stateDate = stateDate;
-
}
-
-
public HeroState clone(){
-
try {
-
return (HeroState) super.clone();
-
} catch (CloneNotSupportedException e) {
-
// TODO Auto-generated catch block
-
e.printStackTrace();
-
}
-
return null;
-
}
- }
点击(此处)折叠或打开
-
/**
-
* 游戏场景状态实体
-
*/
-
public class SceneState implements Cloneable{
-
-
/**
-
* 金币数量
-
*/
-
private int coin;
-
-
/**
-
* 木材数量
-
*/
-
private int wood;
-
-
/**
-
* 地图名称
-
*/
-
private String mapName;
-
-
public int getCoin() {
-
return coin;
-
}
-
-
public void setCoin(int coin) {
-
this.coin = coin;
-
}
-
-
public int getWood() {
-
return wood;
-
}
-
-
public void setWood(int wood) {
-
this.wood = wood;
-
}
-
-
public String getMapName() {
-
return mapName;
-
}
-
-
public void setMapName(String mapName) {
-
this.mapName = mapName;
-
}
-
-
public SceneState clone(){
-
try {
-
return (SceneState) super.clone();
-
} catch (CloneNotSupportedException e) {
-
// TODO Auto-generated catch block
-
e.printStackTrace();
-
}
-
return null;
-
}
- }
点击(此处)折叠或打开
-
/**
-
* 游戏备忘录角色
-
*/
-
public class GameMemento{
-
-
/**
-
* 英雄状态
-
*/
-
private HeroState hState;
-
-
/**
-
* 场景状态
-
*/
-
private SceneState sState;
-
-
/**
-
* 构造方法
-
* @param hState
-
* @param sState
-
*/
-
public GameMemento(HeroState hState,SceneState sState){
-
this.hState = hState.clone();
-
this.sState = sState.clone();
-
}
-
-
/**
-
* 获取备份状态
-
* @return
-
*/
-
public HeroState gethState() {
-
return hState;
-
}
-
-
/**
-
* 获取备份状态
-
* @return
-
*/
-
public SceneState getsState() {
-
return sState;
-
}
- }
点击(此处)折叠或打开
-
/**
-
* 备忘录管理器
-
*/
-
public class Caretaker {
-
-
/**
-
* 备忘录实体
-
*/
-
private GameMemento memento;
-
-
public GameMemento getMemento() {
-
return memento;
-
}
-
-
public void setMemento(GameMemento memento) {
-
this.memento = memento;
-
}
- }
点击(此处)折叠或打开
-
/**
-
* 测试Main方法
-
*/
-
public class TestMain {
-
-
public static void main(String [] args){
-
Game game = new Game();
-
HeroState hState = new HeroState();
-
hState.setHP(100);
-
hState.setMP(100);
-
SceneState sState = new SceneState();
-
sState.setCoin(1000);
-
sState.setWood(1000);
-
game.sethState(hState);
-
game.setsState(sState);
-
System.out.println("游戏状态备份开始");
-
GameMemento memento = game.createMemento();
-
Caretaker ct = new Caretaker();
-
ct.setMemento(memento);
-
System.out.println("游戏状态备份完成");
-
System.out.println("开始游戏,当前英雄生命值:" + game.gethState().getHP());
-
game.play();
-
System.out.println("游戏结束,当前英雄生命值:" + game.gethState().getHP());
-
System.out.println("游戏状态还原开始");
-
game.restore(ct.getMemento());
-
System.out.println("游戏状态还原结束");
-
System.out.println("当前英雄生命值:" + game.gethState().getHP());
-
}
- }
五、总结
备忘录模式
优点:
1)在同一个集合上可有多个状态一起工作
2)不需要为支持迭代而破坏一个集合的封装性。
缺点:
将对象状态备份会占用比较多的系统资源。

本文介绍备忘录模式的基本概念、适用场景及其实现方式,通过游戏状态备份与还原的例子详细阐述了发起人、备忘录和管理者三个角色的作用。
2161

被折叠的 条评论
为什么被折叠?



