版权声明:本文为博主原创文章。只要评论中留言就可以转载。 https://blog.csdn.net/wenzhi20102321/article/details/80468151
走穿java23种设计模式–20备忘录模式详解
备忘录模式,又称快照模式或者Token模式。
一.备忘录模式的现实场景
卢康喜欢玩仙剑奇侠传单机游戏,每闯过一关他都会存档备份一下,防止在下一关的时候打不过去。如果下一关他打不过去,游戏角色死掉了,游戏结束,他可以通过备份重新进去之前备份的地方,直到通过下一关,最终完美通关。
在上面场景中,卢康游戏存档和读档的这两个过程类似于设计模式中的备忘录模式。
二.备忘录模式(Memento Pattern)的定义
在不破化封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将对象恢复到原先保存的状态。
三.备忘录模式的类图
四.备忘录模式的三个角色
1.发起人(Originator)角色
该角色记录当前时刻的内部状态,负责定义哪些属于备份范围的状态,负责创建和恢复备忘数据。
2.备忘录(Memento)角色
该角色负责存储发起人角色的内部状态,在必要时提供发起人需要的内部状态数据。
3.负责人(Caretaker)角色
该角色对备忘录角色进行管理、保存以及提供备忘录。
五.备忘录模式的使用场景
1.需要保存和恢复数据的相关状态场景。
2.需要提供一个可滚动的操作。
3.需要监控副本的场景中。
4.数据库连接的事务管理使用的就是备忘录模式。
五.备忘录模式的注意事项
1.备忘录的生命周期
备忘录创建出来就要在附近代码使用,系统主动管理它的生命周期,建立就要使用,不使用就要立刻删除其引用,等待垃圾回收机制对它进行回收。
2.备忘录的性能
不要在频繁建立备份的场景中使用备忘录模式。
例如,for循环中不宜使用备忘录模式,原因有两点:
(1)不能控制备忘录建立的对象数量;
(2)大对象的建立要消耗大量的资源,系统的性能需要重新考虑。
七.备忘录模式的示例
这里使用上面的现实场景做代码示例。
示例的类图
示例的代码
1.发起人角色GamePlayer
package p20_memento;
/**
* 发起人角色,
* 用来储存需要备份的游戏角色信息和行为
*/
public class GamePlayer {
private String name;//
private int hp;//血量
private int mp;//精气量
private int level;//等级
public GamePlayer(String name, int hp, int mp, int level) {
this.name = name;
this.hp = hp;
this.mp = mp;
this.level = level;
}
//各属性的get、set
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getHp() {
return hp;
}
public void setHp(int hp) {
this.hp = hp;
}
public int getMp() {
return mp;
}
public void setMp(int mp) {
this.mp = mp;
}
public int getLevel() {
return level;
}
public void setLevel(int level) {
this.level = level;
}
//保存备份角色信息
public GameBackup saveBackup() {
System.out.println("保存游戏角色备份。。。");
return new GameBackup(name, hp, mp, level);
}
//恢复游戏角色
public void resumePlayer(GameBackup backup) {
name = backup.getName();
hp = backup.getHp();
mp = backup.getMp();
level = backup.getLevel();
}
//闯关
public void killBoss() {
System.out.println(name + "开始打Boss");
double hpBoss = 100;
while (hp > 0) {
System.out.println(name + "使用技能攻击Boss");
hpBoss = hpBoss - Math.random() * 80;
if (hpBoss <= 0) {
break;
}
mp = mp - 30;
System.out.println("剩余血量:" + hp + "\t剩余精气量" + mp);
System.out.println( "Boss攻击" + name);
hp = hp - 50;
}
if (hp <= 0) {
System.out.println("游戏角色:" + name + "被Boss杀死,Boss还有+" + (int) hpBoss + "+血。");
} else if (hpBoss <= 0) {
System.out.println("游戏角色:" + name + "杀死Boss开始下一关。");
}
}
@Override
public String toString() {
return "游戏角色名:" + name + "\n" +
"血量:" + hp + "\n" +
"精气量" + "\n" +
"等级" + level + "\n";
}
}
2.备忘录角色GameBackup
package p20_memento;
/**
* 备忘录角色,
* 存储备份游戏角色的各个属性
*/
public class GameBackup {
private String name;
private int hp;
private int mp;
private int level;
public GameBackup(String name,int hp,int mp,int level){
this.name=name;
this.hp=hp;
this.mp=mp;
this.level=level;
}
public String getName() {
return name;
}
public int getHp() {
return hp;
}
public int getMp() {
return mp;
}
public int getLevel() {
return level;
}
}
3.负责人角色CaretakePlayer
package p20_memento;
/**
* 负责人角色,
* 控制备份
*/
public class CaretakePlayer {
//游戏备份对象
private GameBackup backup;
public GameBackup getBackup() {
return backup;
}
public void setBackup(GameBackup backup) {
this.backup = backup;
}
}
4.测试类
package p20_memento;
/**
* 测试类
*/
public class MementoDemo {
public static void main(String[] args) {
//创建人物
GamePlayer player = new GamePlayer("习伟", 100, 100, 1);
//控制备份数据的对象
CaretakePlayer caretakePlayer = new CaretakePlayer();
//进行备份
caretakePlayer.setBackup(player.saveBackup());
//打怪
player.killBoss();
//恢复备份
player.resumePlayer(caretakePlayer.getBackup());
System.out.println("====================================");
System.out.println("满血复活。。。");
System.out.println("====================================");
//继续打怪
player.killBoss();
}
}