备忘录模式
简介
备忘录模式是以可以恢复或者说回滚,配置、版本、悔棋为核心功能的设计模式
,而这种设计模式属于行为模式。在功能实现上是以不破坏原对象为基础增加备忘录操作类,记录原对象的行为从而实现备忘录模式。
这个设计在我们平常的生活或者开发中也是比较常见的,比如:后悔药、孟婆汤(一下回滚到0),IDEA编辑和撤销、小霸王游戏机存档。当然还有我们非常常见的Photoshop
角色构成
原发器类(Originator)
:创建一个备忘录对象,使用备忘录存储它的内部状态。
负责人类(CareTaker)
:负责保存好备忘录对象,不能检查或操作备忘录的内容。
备忘录类(Memento)
:将原发器的内部状态存储起来,原发器根据需要决定备忘录存储原发器的哪些内部状态。
代码实现
用一个小例子来简单介绍一下备忘录模式,在玩一个步骤游戏时,每走一步时步数都加一,遇到道具可以快速走几步,或者减几步。用备忘录模式的思想来实现这个逻辑,就是如下代码。
项目结构
游戏类
/**
* 游戏
*/
@Data
public class Game {
/**
* 玩家走的步数
*/
private int playerStep;
/**
* 备份游戏
* @return
*/
public GameMemento createGameMemento(){
return new GameMemento(playerStep);
}
/**
* 开始玩游戏
*/
public void play(){
playerStep = 0;
}
/**
* 恢复备份
* @param gameMemento
*/
public void restore(GameMemento gameMemento){
this.playerStep = gameMemento.getPlayerSteps();
}
}
备份
/**
* 备份
*/
@Getter
public class GameMemento {
/** 步数 */
private int playerSteps;
/**
* 备份步数
* @param playerSteps
*/
public GameMemento(int playerSteps){
this.playerSteps = playerSteps;
}
}
备份信息管理类
/**
* 备份信息管理类
*/
public class Caretaker {
/** 备份 */
private GameMemento gameMemento;
/** 恢复备份 */
public GameMemento retrieveMemento(){
return this.gameMemento;
}
/** 保存备份 */
public void saveMemento(GameMemento gameMemento){
this.gameMemento = gameMemento;
}
}
测试类
public class ApiTest {
@Test
public void testCommand(){
Game game = new Game();
System.out.println("游戏开始,捡到滑板,前进10步");
game.setPlayerStep(10);
//备份当前状态
System.out.println("备份当前状态");
GameMemento gameMemento = game.createGameMemento();
Caretaker caretaker = new Caretaker();
caretaker.saveMemento(gameMemento);
System.out.println("备份完成");
game.play();
System.out.println("踩到便便了,当前步数为:"+game.getPlayerStep());
System.out.println("还原到之前一步");
game.restore(caretaker.retrieveMemento());
System.out.println("恢复完成,当前玩家步数是:"+game.getPlayerStep());
}
}
总结
优点
它提供了一种状态恢复的实现机制
,使得用户可以方便地回到一个特定的历史步骤,当新的状态无效或者存在问题时,可以使用暂时存储起来的备忘录将状态复原。备忘录实现了对信息的封装
,一个备忘录对象是一种原发器对象状态的表示,不会被其他代码所改动。备忘录保存了原发器的状态,采用列表、堆栈等集合来存储备忘录对象可以实现多次撤销操作。
缺点
资源消耗过大,如果需要保存的原发器类的成员变量太多,就不可避免需要占用大量的存储空间,每保存一次对象的状态都需要消耗一定的系统资源。
适用场景
- 保存一个对象在某一个时刻的全部状态或部分状态,这样以后需要时它能够恢复到先前的状态,实现撤销操作。
- 防止外界对象破坏一个对象历史状态的封装性,避免将对象历史状态的实现细节暴露给外界对象。