19.java设计模式之备忘录模式
基本需求
- 游戏的角色有攻击力和防御力,在大战Boss之前保存自身的状态(攻击力和防御力),当大战Boss之后攻击力和防御力下降,从备忘录对象恢复到大战前的状态
传统方案
一个对象,就对应一个保存对象状态的对象

说明
- 一个对象,就对应一个保存对象状态的对象,这样当我们游戏的对象很多时,不利于管理,开销也很大
- 传统的方式是简单的做备份,new出来另外一个对象出来,再把需要备份的数据放到这个新对象,但这就暴露了对象内部的细节
- 可以使用备忘录模式进行解决
基本介绍
备忘录模式(Memento)在 不破坏封装性的前提下,捕获 一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态
可以这里理解备忘录模式:现实生活中的备忘录是用来记录某些要去做的事情,或者是记录已经达成的共同意见的事情,以防忘记了。而在软件层面,备忘录模式有着相同的含义,备忘录对象主要用来记录一个对象的某
种状态,或者某些数据,当要做回退时,可以从备忘录对象里获取原来的数据进行恢复操作备忘录模式属于行为型模式
UML类图(原理)

说明
- Originator:对象,需要保存状态的对象
- Memento:备忘录对象,保存目标对象Originator的内部状态
- Caretaker:守护者对象,保存多个备忘录对象,使用集合管理,提高效率
- 如果希望保存多个Originator对象不同时间的状态,可使用Map<String,List>进行管理
代码实现
// 备忘录对象
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Memento { private String state; } // 目标对象
@Data
public class Originator { private String state; // 创建备忘录对象,用户备份
public Memento createMemento() {
return new Memento(this.state);
} // 从备忘录对象恢复对象
public void restoreFromMemento(Memento memento) {
this.state = memento.getState();
}
} // 守护者对象
public class Caretaker { // 使用集合对备忘录对象进行管理
private List<Memento> mementos; public Caretaker() {
this.mementos = new ArrayList<>();
} // 添加备忘录对象
public void add(Memento memento) {
mementos.add(memento);
} // 根据索引在集合中获取备忘录对象
public Memento getMementoByIndex(int index) {
Memento memento = null;
if (index >= 0 && index < mementos.size()) {
memento = mementos.get(index);
}
return memento;
}
} // 测试
public class Client {
public static void main(String[] args) {
// 创建守护者对象
Caretaker caretaker = new Caretaker();
// 创建目标对象 并设置状态1
Originator originator = new Originator();
originator.setState("状态1 -> 开心");
// 保存状态1 -> 获取备忘录对象,并交由守护者管理
caretaker.add(originator.createMemento());
// 给目标状态设置状态2
originator.setState("状态2 -> 悲伤");
// 保存状态2 -> 获取备忘录对象,并交由守护者管理
caretaker.add(originator.createMemento());
// 给目标状态设置状态3
originator.setState("状态3 -> 笑哭");
// 保存状态3 -> 获取备忘录对象,并交由守护者管理
caretaker.add(originator.createMemento());
// 目标对象当前的状态
System.out.println("目标对象当前的状态是:" + originator.getState());
// 从守护者对象中获取备忘录对象,恢复目标对象状态至状态1
originator.restoreFromMemento(caretaker.getMementoByIndex(0));
System.out.println("目标对象状态恢复到状态1:" + originator.getState());
}
}
UML类图(案例)

代码实现
// 备忘录对象
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Memento { // 攻击力
private int attack; // 防御力
private int defense; } // 游戏角色 亦目标对象
@Data
public class GameRole { // 攻击力
private int attack; // 防御力
private int defense; // 创建目标对象当前状态的备忘录对象
public Memento createMemento() {
return new Memento(this.attack, this.defense);
} // 从备忘录对象中恢复目标对象
public void restoreFromMemento(Memento memento) {
this.attack = memento.getAttack();
this.defense = memento.getDefense();
} // 显示目标对象当前状态
public void display() {
System.out.println("目标对象当前状态,攻击力 -> " + this.attack + "、防御力 -> " + this.defense);
}
} // 守护者对象 对备忘录对象进行管理
@Data
public class Caretaker { // 只保存一次状态 根据本次需求 只需保存一次
private Memento memento;
// 保存一个目标对象的多次状态
// private List<Memento> mementos;
// 保存多个目标对象的多次状态
// private Map<String, List<Memento>> listMap; } // 测试
public class Client {
public static void main(String[] args) {
// 创建守护者对象 管理备忘录对象
Caretaker caretaker = new Caretaker();
// 创建目标对象 并设置初始值
GameRole gameRole = new GameRole();
gameRole.setAttack(100);
gameRole.setDefense(100);
// 获取目标对象当前状态的备忘录对象,并保存至守护者对象中
caretaker.setMemento(gameRole.createMemento());
// 和boss大战前 输出目标对象状态
System.out.println("和boss大战前");
gameRole.display();
// 和boss大战中 输出目标对象状态
System.out.println("和boss大战中");
gameRole.setAttack(50);
gameRole.setDefense(50);
gameRole.display();
// 和boss大战后 使用备忘录对象恢复目标对象状态至初始状态
gameRole.restoreFromMemento(caretaker.getMemento());
System.out.println("和boss大战后,恢复至初始状态");
gameRole.display();
}
}
注意事项
- 给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便的回到某个历史状态
- 实现了信息封装,使得用户不需要关心状态的保存细节
- 如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存
- 应用场景:1、后悔药,2、游戏存档,3、ctrl+z,4、ie中的后退,5、数据库的事务管理
- 为了节约内存,备忘录模式可以和原型模式配合使用
19.java设计模式之备忘录模式的更多相关文章
- 折腾Java设计模式之备忘录模式
原文地址:折腾Java设计模式之备忘录模式 备忘录模式 Without violating encapsulation, capture and externalize an object's int ...
- java设计模式之备忘录模式
备忘录模式 备忘录模式是一种软件设计模式:在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到原先保存的状态.一听到备忘录这个字的时候想起了小小时打的游 ...
- java设计模式9.备忘录模式、访问者模式、调停者模式
备忘录模式 备忘录模式又叫快照模式,备忘录对象是一个用来存储另外一个对象内部状态快照的对象.备忘录的用意是在不破坏封装的条件下,将一个对象的状态捕捉,并外部化存储起来,从而可以在将来合适的时候把这个对 ...
- Java设计模式应用——备忘录模式
备忘录模式主要用于存档.游戏中我们打boss前总会存档,如果打boss失败,则读取存档,重新挑战boss. 可以看出来,备忘录模式一般包括如下数据结构 1. 存档文件:用于恢复备份场景的必要数据: 2 ...
- 观世音甘泉活树的故事竟然是Java设计模式:备忘录模式
目录 定义 意图 主要解决问题 何时使用 优缺点 结构 白箱实现 黑箱实现 多重检查点 观世音甘泉活树的故事 定义 备忘录模式是对象的行为型模式,备忘录对象是一个用来存储另外一个对象内部状态的快照的对 ...
- Java设计模式——装饰者模式
JAVA 设计模式 装饰者模式 用途 装饰者模式 (Decorator) 动态地给一个对象添加一些额外的职责.就增加功能来说,Decorator 模式相比生成子类更为灵活. 装饰者模式是一种结构式模式 ...
- Java设计模式之代理模式(静态代理和JDK、CGLib动态代理)以及应用场景
我做了个例子 ,需要可以下载源码:代理模式 1.前言: Spring 的AOP 面向切面编程,是通过动态代理实现的, 由两部分组成:(a) 如果有接口的话 通过 JDK 接口级别的代理 (b) 如果没 ...
- 浅析JAVA设计模式之工厂模式(一)
1 工厂模式简单介绍 工厂模式的定义:简单地说,用来实例化对象,取代new操作. 工厂模式专门负责将大量有共同接口的类实例化.工作模式能够动态决定将哪一个类实例化.不用先知道每次要实例化哪一个类. 工 ...
- 乐在其中设计模式(C#) - 备忘录模式(Memento Pattern)
原文:乐在其中设计模式(C#) - 备忘录模式(Memento Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 备忘录模式(Memento Pattern) 作者:webabc ...
随机推荐
- Nginx(二):配置文件
nginx.conf 配置文件 nginx 安装目录下,主配置文件 nginx.conf [root@localhost nginx]# cd /etc/nginx/ [root@localhos ...
- react第一单元(简介)
第一单元(react简介) 课程目标 理解react这个框架在前端开发中的地位 理解react诞生的原因和意义(react是一个用于快速构建前端视图的javaScript库) 理解什么是虚拟dom.原 ...
- vue第十七单元(电商项目逻辑处理,电商划分)
第十七单元(电商项目逻辑处理,电商划分) #课程目标 1.什么是电商项目 2.什么是B2B,B2C,C2C模式,常见的电商项目 3.移动端电商项目常见的逻辑处理 4.[知识扩展]传统系统架构及分布式系 ...
- MySQL误删除用户怎么解决
前言:在不考虑到原来用户对关联数据库的授权问题的情况下,有以下两种思路解决 #1.安全模式修改 第一步:关闭数据库服务: [root@db01 ~]#/etc/init.d/mysqld stop 第 ...
- 安装简易OpenShift单节点并配置DNS泛域名
1 楔子 公司有个项目部署在 OpenShift 容器云平台上,出现问题较多,于是萌生在公司环境搭建现场仿真环境,由于资源没有生产环境多,就使用单节点简单模拟下 本文主要内容包括以下: 使用 Dnsm ...
- 解决WebStorme点击谷歌浏览器图标无反应问题
解决思路: 在设置中重新设置谷歌浏览器路径,一定要选中到谷歌浏览器安装目录的Chrome.exe文件,选中后记得apply. 设置步骤: file->seeting->tools-> ...
- JAVA十大经典排序算法最强总结(含JAVA代码实现)
0.排序算法说明 0.1 排序的定义 对一序列对象根据某个关键字进行排序. 0.2 术语说明 稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面: 不稳定:如果a原本在b的前面,而a=b,排 ...
- sql优化的几种方式
一.为什么要对SQL进行优化 我们开发项目上线初期,由于业务数据量相对较少,一些SQL的执行效率对程序运行效率的影响不太明显,而开发和运维人员也无法判断SQL对程序的运行效率有多大,故很少针对SQL进 ...
- springboot(一)入门篇
作者:纯洁的微笑 出处:www.ityouknow.com 版权所有,欢迎保留原文链接进行转载:) 根据原文以下内容略有调整(由于SpringBoot版本更新引起) 什么是spring boot Sp ...
- 任意文件上传——tcp
package chaoba; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; ...