[工作中的设计模式]备忘录模式memento
一、模式解析
备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捕捉(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]
[工作中的设计模式]备忘录模式memento的更多相关文章
- [转] Android中的设计模式-备忘录模式
转自Android中的设计模式-备忘录模式 定义 备忘录设计模式的定义就是把对象的状态记录和管理委托给外界处理,用以维持自己的封闭性. 比较官方的定义 备忘录模式(Memento Pattern)又叫 ...
- [工作中的设计模式]原型模式prototype
一.模式解析 提起prototype,最近看多了js相关的内容,第一印象首先是js的原型 var Person=function(name){ this.name=name; } Person.pro ...
- [工作中的设计模式]解释器模式模式Interpreter
一.模式解析 解释器模式是类的行为模式.给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器.客户端可以使用这个解释器来解释这个语言中的句子. 以上是解释器模式的类图,事实上我 ...
- [工作中的设计模式]中介模式模式Mediator
一.模式解析 用一个中介者对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使耦合松散,而且可以独立地改变它们之间的交互. 中介模式又叫调停者模式,他有如下特点: 1.有多个系统或者对 ...
- [工作中的设计模式]策略模式stategy
一.模式解析 策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法独立于使用它的客户而独立变化. 策略模式的关键点为: 1.多种算法存在 2.算法继承同样的接口 ...
- [工作中的设计模式]建造者模式builder
一.模式解析 建造模式是将复杂的内部创建封装在内部,对于外部调用的人来说,只需要传入建造者和建造工具,对于内部是如何建造成成品的,调用者无需关心. 以上是对建造者模式的官方定义,简单说就是对于复杂对象 ...
- [工作中的设计模式]组合模式compnent
一.模式解析 将对象组合成树形结构以表示“部分整体”的层次结构.组合模式使得用户对单个对象和使用具有一致性. 组合模式的要点是: 1.对象整体以树形层次结构进行展示 2.树的根节点和子节点均可以添加删 ...
- [工作中的设计模式]桥接模式bridge
一.模式解析: 策略模式一节讲过,通过扩展持有者,使持有者形成抽象类,然后实现多个具体持有者,策略模式可以转化为桥接模式. 桥接模式定义为:将抽象部分与实现部分分离,使它们都可以独立的变化,在软件系统 ...
- 备忘录模式 Memento 快照模式 标记Token模式 行为型 设计模式(二十二)
备忘录模式 Memento 沿着脚印,走过你来时的路,回到原点. 苦海翻起爱恨 在世间难逃避命运 相亲竟不可接近 或我应该相信是缘份 一首<一生所爱>触动了多少 ...
随机推荐
- ERROR ITMS-90032 “Invalid image path”
在用 Application Loader上传spa 文件的时候出现这样的错误:ERROR ITMS-90032: "Invalid image path No image found at ...
- ios的链式编程笔记
1.Masonry的语法为啥能连续的使用点语法? >> 底层使用的是:用block当函数的返回参数 > 链式编程思想 2. 使用block当函数的返回参数 // 之前开发中比较习惯 ...
- jvm分析(MD语法)
#是什么**jps** 查看所有的jvm进程,包括进程ID,进程启动的路径等等. **jstack** 观察jvm中当前所有线程的运行情况和线程当前状态.系统崩溃了?如果java程序崩溃生成cor ...
- 双栈排序(codevs 1170)
题目描述 Description Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈 ...
- nyoj1007(euler 函数)
euler(x)公式能计算小于等于x的并且和x互质的数的个数: 我们再看一下如何求小于等于n的和n互质的数的和, 我们用sum(n)表示: 若gcd(x, a)=1,则有gcd(x, x-a)=1: ...
- WMI测试
https://social.msdn.microsoft.com/Forums/windowshardware/zh-CN/c5af7959-95d3-4e1b-ab40-96a2a31c2af2/ ...
- 在asp.net利用jquery.MultiFile实现多文件上传(转载)
转载地址:http://www.cnblogs.com/scy251147/archive/2010/09/30/1839313.html 官网链接:http://www.fyneworks.com/ ...
- 在ubuntu上搭建开发环境9---Ubuntu删除ibus出现的问题及解决
删除 ibus输入法: sudo apt-get install ibus 我们会遇到下面的问题 Ubuntu 14.04 系统设置很多选项消失. 其实遇到这个问题的一个最主要的原因是之前执行过卸载i ...
- win7Java开发环境配置
win7下Java开发环境的配置 首先下载符合操作系统版本的jdk,比如最新的jdk8: 下载链接:http://www.oracle.com/technetwork/java/javase/down ...
- 使用getopt函数对windows命令行程序进行参数解析
getopt()是libc的标准函数,很多语言中都能找到它的移植版本. // -b -p "c:\input" -o "e:\test\output" bool ...