备忘录模式-Memento
备忘录模式用来恢复一个对象的状态到以前的状态。 通俗的说,就是把一个类的属性临时的保存在另一个地方,并提供一个接口可以还原,比较适用的场景是系统升级,代码回滚。
一、类图
备忘录模式包含以下几个角色:
- Originator(原发器):它是一个普通类,可以创建一个备忘录,并存储它的当前内部状态,也可以使用备忘录来恢复其内部状态,一般将需要保存内部状态的类设计为原发器。
- Memento(备忘录):存储原发器的内部状态,根据原发器来决定保存哪些内部状态。备忘录的设计一般可以参考原发器的设计,根据实际需要确定备忘录类中的属性。需要注意的是,除了原发器本身与负责人类之外,备忘录对象不能直接供其他类使用,原发器的设计在不同的编程语言中实现机制会有所不同。
- Caretaker(负责人):负责人又称为管理者,它负责保存备忘录,但是不能对备忘录的内容进行操作或检查。在负责人类中可以存储一个或多个备忘录对象,它只负责存储对象,而不能修改对象,也无须知道对象的实现细节。
二、示例
考虑平时玩的通关游戏,每走一步时步数都加一,遇到道具可以快速走几步,或者减几步。用备忘录模式的思想来实现这个逻辑。
游戏类:
class Game { /** * 玩家走的步数 */ private int playerStep; /** * 备份游戏 */ public GameMemento createGameMemento() { return new GameMemento(playerStep); } /** * 开始玩游戏 */ public void play() { playerStep = 0; } /** * 恢复备份 */ public void restore(GameMemento gameMemento) { this.playerStep = gameMemento.getPlayerSteps(); } }
备份
/** * 备份 */ class GameMemento { /** * 步数 */ private int 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 Player { public static void main(String[] args) { 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()); } }
三、备忘录模式的优缺点和适用场景
优点:
当发起人角色中的状态改变时,有可能这是个错误的改变,我们使用备忘录模式就可以把这个错误的改变还原。
备份的状态是保存在发起人角色之外的,这样,发起人角色就不需要对各个备份的状态进行管理。
缺点:
在实际应用中,备忘录模式都是多状态和多备份的,发起人角色的状态需要存储到备忘录对象中,对资源的消耗是比较严重的。
……更多设计模式的内容,可以访问Refactoring.Guru
不积跬步,无以至千里。不积小流,无以成江海!