一.模式定义
备忘录模式(Memento Pattern):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
Memento Pattern:Without violating encapsulation, capture and externalize an object's internal state so that the object can be restored to this state later.
二.模式要素
发起人角色Originator:记录当前时刻的内部状态,负责定义哪些属于备份范围的状态,负责创建和恢复备忘录数据。
备忘录角色Memento:负责存储Originator发起人对象的内部状态,在需要的时候提供发起人需要的内部状态。
备忘管理员角色Caretaker:对备忘录进行管理、保存和提供备忘录。
三.举例说明
我们举个游戏存档的例子吧。你在玩某个游戏的时候经常会对游戏进行存档,当想要从存档处玩的时候就读取存档并开始游戏。
就这个非常浅显的场景中。游戏本身就是Originator,存档当然就是Memento了,保存存档的文件区域可以坎组CareTaker。那要怎么实现呢?开撸代码!
四.具体代码
Game.java 游戏类
package mementopattern;
/**
* author: lllddd
* created on: 2021/3/16 19:38
* description:游戏类
*/
public class Game {
// 游戏进度
private String gameProgress;
public Game() {
}
/**
* 获取当前的游戏进度
*
* @return 游戏进度
*/
public String getGameProgress() {
return gameProgress;
}
/**
* 设置当前游戏进度
*
* @param gameProgress 游戏进度
*/
public void setGameProgress(String gameProgress) {
this.gameProgress = gameProgress;
}
/**
* 保存游戏进度,生成对应的进度备份
*
* @return 游戏进度备份
*/
public Backup saveProgress() {
return new Backup(gameProgress);
}
/**
* 加载备份
*
* @param backup 备份
*/
public void loadBackup(Backup backup) {
if (backup != null) {
gameProgress = backup.getGameProgress();
}
}
}
Backup.java 备份类
package mementopattern;
/**
* author: lllddd
* created on: 2021/3/16 19:40
* description:游戏备份类
*/
public class Backup {
// 游戏进度
private String gameProgress;
public Backup(String gameProgress) {
this.gameProgress = gameProgress;
}
/**
* 获取游戏进度
*
* @return 游戏进度
*/
public String getGameProgress() {
return gameProgress;
}
}
BackupZone.java 备份区类
package mementopattern;
import java.util.LinkedList;
import java.util.List;
/**
* author: lllddd
* created on: 2021/3/16 19:41
* description:游戏备份存储区
*/
public class BackupZone {
// 游戏进度存储集合
private List<Backup> gameBackups;
public BackupZone() {
gameBackups = new LinkedList<>();
}
/**
* 添加备份
*
* @param backup
*/
public void add(Backup backup) {
if (backup != null) {
gameBackups.add(backup);
}
}
/**
* 获取备份
*
* @param index 游标
* @return 游戏备份
*/
public Backup getBackup(int index) {
if (gameBackups != null && gameBackups.get(index) != null) {
return gameBackups.get(index);
}
return null;
}
}
Main.java 调用类
package mementopattern;
/**
* author: lllddd
* created on: 2021/3/16 19:37
* description:调用类
*/
public class Main {
public static void main(String[] args) {
Game game = new Game();
BackupZone backupZone = new BackupZone();
System.out.println("开始游戏 >>>\n");
game.setGameProgress("游戏场景1");
System.out.println("正在运行:" + game.getGameProgress());
game.setGameProgress("游戏场景2");
System.out.println("正在运行:" + game.getGameProgress());
System.out.println("存档游戏 >>>");
backupZone.add(game.saveProgress());
game.setGameProgress("游戏场景3");
System.out.println("正在运行:" + game.getGameProgress());
System.out.println("存档游戏 >>>");
backupZone.add(game.saveProgress());
Backup backup1 = backupZone.getBackup(0);
System.out.println("\n第1个存档:" + backup1.getGameProgress());
Backup backup2 = backupZone.getBackup(1);
System.out.println("\n第2个存档:" + backup2.getGameProgress());
System.out.println("\n加载第1个存档 >>>");
game.loadBackup(backup1);
System.out.println("正在运行:" + game.getGameProgress());
System.out.println("\n加载第2个存档 >>>");
game.loadBackup(backup2);
System.out.println("正在运行:" + game.getGameProgress());
}
}
运行结果:
五.总结
1.备忘录模式的优点
(1)给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。
(2)实现了信息的封装,使得用户不需要关心状态的保存细节。
2.备忘录模式的缺点
(1)消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。
3.备忘录模式的适用场景
(1)需要保存和恢复数据的相关状态场景。
(2)提供一个可回滚的操作。
(3)适用于需要监控的副本场景。
(4)数据库连接的事物管理就是备忘录模式。