您的位置:首页 > 其它

[工作中的设计模式]备忘录模式memento

2016-02-05 01:03 453 查看
一、模式解析

  备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捕捉(Capture)住,并外部化,存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。备忘录模式常常与命令模式和迭代子模式一同使用。

  备忘录模式可以根据客户指令,将相应的对象特有属性进行快照,如果客户要恢复对象,则根据快照提供的特有属性进行还原。

二、模式代码

package memento.patten;
/**
*备忘录类,同时指定要保存的对象属性
* @author zjl
* @time 2016-2-1
* 备忘录:仅有一个状态需要保存
* @author zjl
* @time 2016-2-1
*
*/
public class Memento {
private String state;
public Memento(String state){
this.state=state;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}


2、发起者决定备忘录的属性,已经生成备忘录和还原备忘录的方法

package memento.patten;

public class Originator {
public String state;

public String getState() {
return state;
}

public void setState(String state) {
this.state = state;
}
/**
* 生成备忘录
* @return
*/
public Memento createMemento(){
return new Memento(state);
}
public void restoreMemento(Memento memento){
this.setState(memento.getState());
}

}


3、 备忘录保存的类

package memento.patten;

public class Caretaker {
private Memento memento;

public Memento getMemento() {
return memento;
}

public void setMemento(Memento memento) {
this.memento = memento;
}

}


5、客户端调用

package memento.patten;

public class Client {
public static void main(String[] args) {
Originator originator=new Originator();
originator.setState("状态1");
System.out.println("初始状态为:"+originator.getState());
Caretaker caretaker=new Caretaker();
caretaker.setMemento(originator.createMemento());

originator.setState("状态2");
System.out.println("当前状态为:"+originator.getState());

//恢复备份
originator.restoreMemento(caretaker.getMemento());
System.out.println("恢复后状态为:"+originator.getState());

}
}


三、疑问



以上是备忘录模式的UML图,一直以来的模式均为提供UML图,但是备忘录是个特例,有几个问题需要这里:

1、发起人需要确定保存哪些信息,并提供保存和还原方法,整个设计模式缺少了对被保存对象的定义所以看起来并不完整
2、管理角色目前仅提供了备忘录的引用,实际中可能存在多个备忘录的保存,因此需要保存备忘录集合

所以我们在场景中需要进行完善。

四、场景

由于做的大部分项目对于功能节点的保存和还原均使用持久化技术,包括数据库和问题进行保存,因此使用备忘录的模式很少,不过我们仍然可以通过一些常见的场景进行模拟。

我们进场玩的单机游戏,有如下元素

游戏界面:人物显示,调取存档指令,还原指令

人物:游戏角色,有等级、血量、防御、经验的要素,人物有工具,防守,升级的动作

存档:存档中不需要人物动作,只需要保留基本信息即可

存档中心:可以保存多个存档

客户端:客户仅和游戏界面进行打交道

五、场景代码

package memento.example;

/**
* 游戏类,
* 游戏的主界面,主要运行游戏,生成存档以及还原存储
* 此处省略运行游戏逻辑
* @author zjl
* @time 2016-2-1
*
*/
public class Game {
//游戏角色
public Role role;
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
public SaveCenter center=new SaveCenter();

public void createSave(int pos,Role role){
center.save(pos, new Save(role));
}
public void restoreSave(int pos){
this.role.setLevel(center.getSave(pos).getLevel());
}
}


2、游戏角色

package memento.example;
/**
* 游戏角色,有等级,生命,攻击力,防守力
* @author zjl
* @time 2016-2-1
*
*/
public class Role {
private int level;
private int vit;//生命
private int atk;//攻击力
private int def;//防守
public Role(int level){
this.setLevel(level);
}

public void setLevel(int level){
this.level=level;
this.vit=level*400;
this.atk=level*20;
this.def=level*5;

}
public int getLevel(){
return this.level;
}

public int getVit() {
return vit;
}
public void setVit(int vit) {
this.vit = vit;
}
public int getAtk() {
return atk;
}
public void setAtk(int atk) {
this.atk = atk;
}
public int getDef() {
return def;
}
public void setDef(int def) {
this.def = def;
}

public void levelup(){
setLevel(this.level+1);
}

@Override
public String toString() {
return "Role [level=" + level + ", vit=" + vit + ", atk=" + atk + ", def=" + def + "]";
}

}


3、游戏存档

package memento.example;
/**
* 游戏存档,保存任务等级,如果有其他信息也可以一并保存
* @author zjl
* @time 2016-2-1
*
*/
public class Save {
private int level;

public Save(Role role){
this.level=role.getLevel();
}

public int getLevel() {
return level;
}

public void setLevel(int level) {
this.level = level;
}

}


4、存档中心

package memento.example;

import java.util.HashMap;
import java.util.Map;

/**
* 存档中心
* 可以有多个存档,根据位置进行保存
* @author zjl
* @time 2016-2-1
*
*/
public class SaveCenter {
public Map<Integer, Save> map=new HashMap<Integer, Save>();

public void save(int pos,Save save){
map.put(pos, save);
}
public Save getSave(int pos){
return map.get(pos);
}

}


5、玩家界面

package memento.example;

public class Client {
public static void main(String[] args) {
Game game=new Game();
Role lixiaoyao=new Role(1);
game.setRole(lixiaoyao);
System.out.println(game.getRole());

game.createSave(1, game.getRole());
game.getRole().levelup();
System.out.println(game.getRole());
game.getRole().levelup();
System.out.println(game.getRole());
game.restoreSave(1);
System.out.println(game.getRole());

}
}


6、执行结果

Role [level=1, vit=400, atk=20, def=5]
Role [level=2, vit=800, atk=40, def=10]
Role [level=3, vit=1200, atk=60, def=15]
Role [level=1, vit=400, atk=20, def=5]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: