实例讲解JAVA设计模式之备忘录模式
作者:认真对待 发布时间:2023-08-29 16:31:19
标签:JAVA,备忘录模式,设计模式
在讲述这个模式之前,我们先看一个案例:游戏回档
游戏的某个场景,一游戏角色有生命力、攻击力、防御力等数据,在打Boss前和后会不一样,我们允许玩家如果感觉与Boss决斗的效果不理想,可以让游戏恢复到决斗前。下面是代码:
游戏角色类,用来存储角色的生命力、攻击力、防御力的数据。
public class GameRole {
private int vit;//生命力
private int atk;//攻击力
private int def;//防御力
//状态显示
public void stateDisplay() {
System.out.println("当前角色状态:");
System.out.println("体力:"+this.vit);
System.out.println("攻击力"+this.atk);
System.out.println("防御力"+this.def);
}
//获取初始状态
public void getInitState() {
//数据通常来自本地磁盘或远程数据库
this.vit = 100;
this.atk = 100;
this.def = 100;
}
//战斗
public void fight() {
//在与Boss大战后游戏数据损耗为0
this.vit = 0;
this.atk = 0;
this.def = 0;
}
//省略getter、setter方法
}
//测试方法
public class Test {
public static void main(String[] args) {
//大战Boss前
GameRole lixiaoyao = new GameRole();
lixiaoyao.getInitState();//Boss大战前,获得角色初始状态
lixiaoyao.stateDisplay();
//保存进度,通过游戏角色的新实例来保存进度
GameRole backup = new GameRole();
backup.setVit(lixiaoyao.getVit());
backup.setAtk(lixiaoyao.getAtk());
backup.setDef(lixiaoyao.getDef());
//大战Boss时,损耗严重,所有数据全部损耗为0
lixiaoyao.fight();
lixiaoyao.stateDisplay();
//恢复之前状态,重新来玩
lixiaoyao.setVit(backup.getVit());
lixiaoyao.setAtk(backup.getAtk());
lixiaoyao.setDef(backup.getDef());
lixiaoyao.stateDisplay();
}
}
上面的代码实现了效果,但是不理想的是:main方法里暴露了太多“细节”,使得main方法需要知道“生命力、攻击力、防御力”这样的细节。以后需要增加“魔法值”或修改现有的“生命力”为“经验值”,这部分就要修改了。同样的道理也存在于恢复时的代码。显然,我们希望的是把这些“游戏角色”的存取状态细节封装起来,而且最好是封装在外部的类中。以体现职责分离。
下面介绍备忘录模式:
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可将该对象恢复到原先保存的状态。
用备忘录模式优化案例
public class GameRole {
private int vit;//生命力
private int atk;//攻击力
private int def;//防御力
//状态显示
public void stateDisplay() {
System.out.println("当前角色状态:");
System.out.println("体力:"+this.vit);
System.out.println("攻击力"+this.atk);
System.out.println("防御力"+this.def);
}
//获取初始状态
public void getInitState() {
//数据通常来自本地磁盘或远程数据库
this.vit = 100;
this.atk = 100;
this.def = 100;
}
//战斗
public void fight() {
//在与Boss大战后游戏数据损耗为0
this.vit = 0;
this.atk = 0;
this.def = 0;
}
//新增“保存角色状态”方法,将游戏角色的三个状态值通过实例化“角色状态存储箱”返回
public RoleStateMemento saveState() {
return new RoleStateMemento(vit, atk, def);
}
//新增“恢复角色状态”方法,可将外部的“角色状态存储箱”中的状态值恢复给游戏角色
public void recoveryState(RoleStateMemento memento) {
this.vit = memento.getAtk();
this.atk = memento.getAtk();
this.def = memento.getDef();
}
//省略getter、setter方法
}
//角色状态存储箱类
public class RoleStateMemento {
private int vit;//生命力
private int atk;//攻击力
private int def;//防御力
//将生命力、攻击力、防御力存入状态存储箱对象中
public RoleStateMemento(int vit, int atk, int def) {
super();
this.vit = vit;
this.atk = atk;
this.def = def;
}
//省略getter、setter方法
}
//角色状态管理者类
public class RoleStateCaretaker {
private RoleStateMemento memento;
public RoleStateMemento getMemento() {
return memento;
}
public void setMemento(RoleStateMemento memento) {
this.memento = memento;
}
}
//测试方法
public class Test {
public static void main(String[] args) {
//大战Boss前
GameRole lixiaoyao = new GameRole();
lixiaoyao.getInitState();//Boss大战前,获得角色初始状态
lixiaoyao.stateDisplay();
//保存进度,由于封装在Memento中,因此我们并不知道保存了哪些具体的数据
RoleStateCaretaker stateAdmin = new RoleStateCaretaker();
stateAdmin.setMemento(lixiaoyao.saveState());
//大战Boss时,损耗严重
lixiaoyao.fight();
lixiaoyao.stateDisplay();
//恢复之前的状态
lixiaoyao.recoveryState(stateAdmin.getMemento());
lixiaoyao.stateDisplay();
}
}
输出结果同上。
肯定有人会问:对于“角色状态”的保存,直接调用RoleStateMemento进行set和get不就行了,为什么还需要一个RoleStateCaretaker类呢?
这是为了符合迪米特法则进行的优化!
备忘录模式也是有缺点的,角色状态需要完整存储到备忘录对象中,如果状态数据很大很多,那么在资源消耗上,备忘录对象会非常耗内存。所以也不是用的越多越好。
来源:https://www.cnblogs.com/jwen1994/p/10165657.html


猜你喜欢
- RestTemplate反序列化嵌套对象假设某个接口返回的数据如下格式{ "msg" : "ok&
- ps:我用的版本是7.0.5场景:左侧第一列宽度不够,导致数据换行。Table table = new Table(new float[2]
- 安装jdk1.7.0_04后,同时设置环境变量,并且source。可是java -version查看后,还是只能查看到jdk1.6和jdk1
- 我就废话不多说了,大家还是直接看代码吧~/// <summary> /// 字符串转Unicode //
- 一、NIO基本简介NIO (New lO)也有人称之为java non-blocking lO是从Java 1.4版本开始引入的一个新的IO
- 异步客户端套接字示例 下面的示例程序创建一个连接到服务器的客户端。该客户端是用异步套接字生成的,因此在等待服务器返回
- 1. 认识ZoneZone像一个沙盒,是我们代码执行的一个环境。我们的main函数默认就运行在Root Zone当中。子Zone的构造有点像
- 集成引入依赖在项目的pom.xml中增加以下依赖<dependency> <groupId>org.s
- 一、概述有不少人问我intellij idea的mybatis-plus自动生成插件使用出现各种各样的问题,所以我在这边博客的基础上添加一些
- springboot集成mybatis plus和dynamic-datasource注意事项环境spring-boot-starter-p
- 本文实例为大家分享了Android倒计时的开始与停止,剩余时分秒的展示效果,供大家参考,具体内容如下1.声明开启倒计时相关方法Handler
- 最近做一个小玩意需要识别验证码,之前从来没有接触过识别验证码这块,这可难倒了我。所以,在网上搜索如何识别验证码,许多前辈写的博文教会了我。怕
- 本文主要介绍在SpringMVC框架整合Junit框架进行单元测试。闲话少述,让我们直入主题。系统环境软件版本spring-webmvc4.
- 这篇文章主要介绍了mybatis insert返回主键代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,
- 本文为大家分享了Swing单选按钮和复选框的使用方法,供大家参考,具体内容如下JRadioButton构造函数:JRadioButton()
- 做了Android开发这么久了,经常会遇到一个问题是adb端口被占用,大家都知道Android默认的adb端口是5037,电脑上有一些应用的
- 背景在开发需求当中,当有总收益、总用户数等数字要显示时,为了更好的给用户提供展示效果,往往会想加入炫酷的数字滚动动画,使呆板平静的数字变得灵
- 一、系统介绍 1.系统功能登录系统查询信息新增信息修改信息删除信息2.环境配置JDK版本:1.8Mysql:8.0.133.数据库
- 目录前言开始总结前言小伙伴们都知道,现在市面上最流行的web开发框架就是springboot了,在springboot开始流行之前,我们都用
- Java 8 lambda表达式引入详解及实例eclipse下载安装Help -> EclipseMarketplace ->