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节点的解析文章的最后部分,我们提到了动态代理的概念,下面我们就简单了解一下动态代理. 一,概念 代理设计模式的目的就是在不直接操作对象的前 ...
随机推荐
- 关于搭建Session服务器(转载)
Session服务器配置指南与使用经验 一.摘要 所有Web程序都会使用Session保存数据. 使用独立的Session服务器可以解决负载均衡场景中的Session共享问题.本文介绍.NET平台下建 ...
- node中间层
node中间层 一.总结 1.node中间层作用:前端也是mvc,NodeJS之后,前端可以更加专注于视图层,而让更多的数据逻辑放在Node层处理 2.node中间层作用:当发现所有请求量太多应付不过 ...
- vue 自定义分页组件
vue2.5自定义分页组件,可设置每页显示条数,带跳转框直接跳转到相应页面 Pagination.vue 效果如下图: all: small(只显示数字和上一页和下一页): html <temp ...
- Servlet的异常处理机制
一 声明式异常处理 在web.xml中对声明对各种异常的处理方法. 通过 <error-page>元素来声明. 此元素的结构如下: +------ ...
- 15.SpringBoot简介-SpringBoot是什么可以做什么
转自:https://blog.csdn.net/kingboyworld/article/details/77713743 在过去的两年时间里,最让人兴奋.回头率最高.最能改变游戏规则的东西,大概就 ...
- 2.JPA学习总结
转自:https://shmilyaw-hotmail-com.iteye.com/blog/1969190 前言 最近在做一个项目的时候因为牵涉到要对数据库的操作,在最开始实现的时候采用了直接的JD ...
- Altium Designer中的粉红色网格和绿色框框
- opencv cvtColor dtype issue(error: (-215) )
opencv cvtColor dtype issue(error: (-215) ) 更详细的错误信息如下,color.cpp:9710: error: (-215) depth == CV_8U ...
- express 学习笔记(一)路由
先导入express: var express = require('express'); var app = express(); 1.路由方法: get, post, put, head, del ...
- JavaScript中双叹号“!!”作用
1.JavaScript的逻辑非(!)操作符的作用 (逻辑非) 如果操作数能够转换为true则返回false:否则返回true. 2.!!的作用 !!一般用来将后面的表达式强制转换为布尔类型的数据(b ...