Java设计模式之从[暗黑破坏神存档点]分析备忘录(Memento)模式
在大部分游戏中,都有一个“存档点”的概念。比如,在挑战boss前,游戏会在某个地方存档,假设玩家挑战boss失败,则会从这个存档点開始又一次游戏。因此,我们能够将这个“存档点”当成是一个备忘录,我们将此时玩家全部的状态保存下来,以便之后的读取。
备忘录模式正是如此,它在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就能够将该对象恢复到原先的保存状态了。
一个简单的样例,如果玩家在暗黑破坏神中准备挑战Boss巴尔,玩家携带了10瓶药剂,而且在巴尔的门前“世界之石”存了档,玩家在挑战Boss时使用了1瓶药剂,后来挑战失败了,于是他又一次读档,再次回到了世界之石,此时他身上携带的药剂数量仍然应该为10瓶。
详细的代码例如以下:
interface IMemento{
}
class CharacterOriginator{
private int potion;
private String position;
public void move(String place){
position = place;
}
public void usePotion(){
potion --;
}
public int getPotion() {
return potion;
}
private void setPotion(int potion) {
this.potion = potion;
}
public String getPosition() {
return position;
}
private void setPosition(String position) {
this.position = position;
}
public IMemento createMemento(){
return new Memento(potion, position);
}
public void restoreMemento(IMemento memento){
setPotion(((Memento)memento).getPotion());
setPosition(((Memento)memento).getPosition());
}
public CharacterOriginator(int potion, String position){
this.potion = potion;
this.position = position;
}
private class Memento implements IMemento{
private int potion;
String position;
public Memento(int potion, String position){
this.potion = potion;
this.position = position;
}
public int getPotion() {
return potion;
}
public String getPosition() {
return position;
}
}
}
class Caretaker{
IMemento memento;
public IMemento getMemento() {
return memento;
}
public void setMemento(IMemento memento) {
this.memento = memento;
}
}
class Memento
{
public static void main(String[] args) {
CharacterOriginator player = new CharacterOriginator(10, "世界之石");
Caretaker caretaker = new Caretaker();
caretaker.setMemento(player.createMemento());
System.out.printf("玩家携带的药剂:%d,所在位置:%s\n", player.getPotion(), player.getPosition());
player.usePotion();
player.move("巴尔的宫殿");
//玩家挑战失败后又一次读档
System.out.printf("玩家携带的药剂:%d,所在位置:%s\n", player.getPotion(), player.getPosition());
player.restoreMemento(caretaker.getMemento());
System.out.printf("玩家携带的药剂:%d,所在位置:%s\n", player.getPotion(), player.getPosition());
}
如今来分析一下上面的代码,并同一时候解说备忘录模式。备忘录模式有3个參与者:Originator——负责创建备忘录、还原备忘录,人物的各种状态都在此,如样例中的CharacterOriginator。Memento——备忘录,它表示须要存储哪些数据,Originator通过须要在备忘录上取数据。在上例中,Memento为Originator的一个内部类。Caretaker——负责保存、获取Memento。为了不暴露Memento的内部方法(我们觉得,Memento的内部方法仅仅能由CharacterOriginator获取),我们让Memento继承了一个空接口IMemento,因此通过Caretaker获得的备忘录均是IMemento类型的,我们无法对它做不论什么事情,可是能够把它传给CharacterOriginator,然后Originator的restoreMemento能够把IMemento类型强制转换为Memento类型。请注意,因为Memento为内部私有类,因此除了CharacterOriginator外,其余的类无法调用Memento的方法,这也就是我们说的“不暴露Memento内部方法”。restoreMemento中清晰写明了应该还原哪些状态,在这里就不进行详解了。
最后我们看看main方法。首先实例化了一个玩家(player),他有10瓶药水,位于世界之石;随后他进入了巴尔的宫殿,并用掉了一瓶药水;最后,他因为挑战失败而恢复到了曾经的存档点——拥有10瓶药水,位于世界之石。因此,程序执行的结果为:
玩家携带的药剂:10,所在位置:世界之石
玩家携带的药剂:9,所在位置:巴尔的宫殿
玩家携带的药剂:10,所在位置:世界之石
以上就是备忘录模式的说明,希望能对大家有所帮助。
Java设计模式之从[暗黑破坏神存档点]分析备忘录(Memento)模式的更多相关文章
- JAVA设计模式-动态代理(Proxy)源码分析
在文章:JAVA设计模式-动态代理(Proxy)示例及说明中,为动态代理设计模式举了一个小小的例子,那么这篇文章就来分析一下源码的实现. 一,Proxy.newProxyInstance方法 @Cal ...
- Java并发系列[2]----AbstractQueuedSynchronizer源码分析之独占模式
在上一篇<Java并发系列[1]----AbstractQueuedSynchronizer源码分析之概要分析>中我们介绍了AbstractQueuedSynchronizer基本的一些概 ...
- Java并发系列[3]----AbstractQueuedSynchronizer源码分析之共享模式
通过上一篇的分析,我们知道了独占模式获取锁有三种方式,分别是不响应线程中断获取,响应线程中断获取,设置超时时间获取.在共享模式下获取锁的方式也是这三种,而且基本上都是大同小异,我们搞清楚了一种就能很快 ...
- Java设计模式六大原则之场景应用分析
定义:不要存在多于一个导致类变更的原因. 通俗的说.即一个类仅仅负责一项职责. 问题由来:类T负责两个不同的职责:职责P1,职责P2.当由于职责P1需求发生改变而须要改动类T时,有可能会导致原本执行正 ...
- 【java设计模式】之 抽象工厂(Abstract Factory)模式
1. 女娲的失误 上一节学习了工厂模式,女娲运用了该模式成功创建了三个人种,可是问题来了,她发现没有性别--这失误也忒大了点吧--竟然没有性别,那岂不是--无奈,只好抹掉重来了,于是所有人都被消灭掉了 ...
- Java设计模式从精通到入门五 抽象工厂方法模式
定义 抽象工厂类为创建一组相关和相互依赖的对象提供一组接口,而无需指定一个具体的类. 这里我得把工厂方法模式得定义拿出来做一下比较:定义一个创建对象的接口,由子类决定实例化哪一个类.工厂方法是一个 ...
- C++设计模式实现--备忘录(Memento)模式
一. 备忘录模式 定义:在不破坏封装性的前提下,捕获一个对象的内部状态.并在该对象之外保存这个状态. 这样以后就可将该对象恢复到原先保存的状态. 结构图: 使用范围: Memento 模式比較适用于功 ...
- 设计模式C++描述----17.备忘录(Memento)模式
一. 备忘录模式 定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到原先保存的状态. 结构图: 使用范围: Memento 模式比较适用于功能 ...
- JAVA设计模式-动态代理(Proxy)示例及说明
在Mybatis源码解析,一步一步从浅入深(五):mapper节点的解析文章的最后部分,我们提到了动态代理的概念,下面我们就简单了解一下动态代理. 一,概念 代理设计模式的目的就是在不直接操作对象的前 ...
随机推荐
- select发生改变使用js提交form表单(get传值)
form表单如下: <form id="my_form" method="get" action=""> <input t ...
- 原生JavaScript 封装ajax
原生JavaScript 封装ajax function myajax(options){ //新建一个局部对象 用来存放用户输入的各种参数 var opt={ type:options.type ...
- 阻止事件冒泡js jquery
jQuery之防止冒泡事件 冒泡事件就是点击子节点,会向上触发父节点.祖先节点的点击事件. 以下是html代码部分: <body> <div id="content&quo ...
- Node.js笔记(九)Nodejs与shell
众所周知.Nodejs是单进程异步执行的.但不光是单进程,Nodejs也提供了多进程方面的支持 其创始人应该还是比較重视这一块的,最有力的证据就是child_process是Nodejs核心模块之中的 ...
- Jquery获取select选中的option的文本信息
注意:以下用的$(this)代表当前选中的select框 第一种: $(this).children("option:selec... ...查看全文
- setting.system-全局属性的设定
SystemProperties跟Settings.System 1 使用 SystemProperties.get如果属性名称以“ro.”开头,那么这个属性被视为只读属性.一旦设置,属性值不能改变. ...
- Nginx日志优化
一 日志轮训切割 [root@centos7 tools]# cat nginx_log.sh #!/bin/bash cd /var/log/nginx/ &&\ /bin/mv a ...
- 绝对定位等html结构,水平居中的处理方案
1.父子结构,父relative,子absolute.子元素要水平居中:left:50%:margin-left:子元素一半的宽度.因为定位的left是按左边框开始计算.[固定问题的模块化解决]
- jquery如何实现表单post方式提交
jquery如何实现表单post方式提交 一.总结 一句话总结:即使js给form对象提供了submit()方法,那也不意为表单中可以不写提交按钮这个元素,即form表单依然需要五脏俱全才可以使用js ...
- 如何在本地运行查看github上的开源项目
看中了一款很多星星的github的项目,想把这个项目拉到自己的电脑上运行查看项目效果,该怎么做?示例:我们今天要看的 github项目地址:https://github.com/lzxb/vue-cn ...