实例讲解JAVA设计模式之备忘录模式

作者:认真对待 时间:2023-08-29 16:31:19 

在讲述这个模式之前,我们先看一个案例:游戏回档

游戏的某个场景,一游戏角色有生命力、攻击力、防御力等数据,在打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

标签:JAVA,备忘录模式,设计模式
0
投稿

猜你喜欢

  • 一篇超详细的Spring Boot整合Mybatis文章

    2022-01-27 10:02:58
  • java中不定长参数的实例用法

    2021-06-17 02:49:35
  • Java新手学习之IO流的简单使用

    2023-08-09 15:57:33
  • Java回调函数实例代码详解

    2023-11-23 18:22:26
  • Java计算器核心算法代码实现

    2022-03-18 05:38:55
  • Winform窗体效果实例分析

    2023-12-12 04:44:08
  • java注解的全面分析

    2023-11-25 11:28:50
  • 详解SpringCloud Config配置中心

    2021-06-18 04:38:34
  • SpringCloud学习笔记之Feign远程调用

    2023-08-15 09:57:01
  • springboot开启声明式事务的方法

    2021-06-18 23:50:48
  • java虚拟机深入学习之内存管理机制

    2023-07-03 21:15:40
  • java如何去除图片中的白色背景

    2022-04-17 00:07:14
  • C语言示例讲解while循环语句的用法

    2023-09-13 01:44:40
  • javassist使用指南

    2023-03-04 17:03:00
  • android教程之把自己的应用加入到系统分享中

    2022-05-13 11:38:41
  • C++中string字符串分割函数split()的4种实现方法

    2023-02-05 23:28:48
  • C++基础概念讲述

    2022-10-31 16:56:05
  • spring boot项目快速构建的全步骤

    2023-11-16 21:16:38
  • MybatisPlus整合Flowable出现的坑及解决

    2022-03-28 22:56:35
  • JPA save()方法将字段更新为null的解决方案

    2023-10-28 22:29:28
  • asp之家 软件编程 m.aspxhome.com