个人随笔
目录
十九、行为型-类的状态-备忘录(Memento)模式
2020-09-09 21:46:05

现在我们来学习第三种设计模式行为型的第三类,类的状态中的第一种备忘录模式,这种模式的使用场景很多,比如游戏中的存档读档。下面我们来一起学习吧。

1、备忘录模式

在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
使用场景: 1、需要保存/恢复数据的相关状态场景。 2、提供一个可回滚的操作。

2、涉及角色

  1. Originator(发起人):负责创建一个备忘录Memento,用以记录当前时刻自身的内部状态,并可使用备忘录恢复内部状态。Originator可以根据需要决定Memento存储自己的哪些内部状态。
  2. Memento(备忘录):负责存储Originator对象的内部状态,并可以防止Originator以外的其他对象访问备忘录。备忘录有两个接口:Caretaker只能看到备忘录的窄接口,他只能将备忘录传递给其他对象。Originator却可看到备忘录的宽接口,允许它访问返回到先前状态所需要的所有数据。
  3. Caretaker(管理者):负责备忘录Memento,不能对Memento的内容进行访问或者操作。

3、例子

这里举一个游戏读档存档的例子,游戏中有游戏的用户姓名,游戏等级,分数。我们游戏过程中可以存档用户的等级和分数,姓名就没必要存档,以防服务器崩溃或者被BOSS杀死等级和分数重新变为0。哈哈哈真正游戏过程中当然不会因为被BOSS杀死就变为0,或者服务器崩溃变为0,这里举个例子而已。

4、UML

User是发起人:是游戏角色,可以主动存档和读档。
Memento是备忘录,这里用户每次都会新建一个备忘录,只会备忘用户的等级和分数。
Manager是管理者,可以管理备忘录,只有管理的权限不能够修改备忘录的内容。

我这里管理者只是保存一个备忘录,理论上最好用一个map来保存,然后key为用户的ID,这样子就可以管理超级多备忘录,毕竟一个游戏有超级多用户。这里举个例子就不用那么麻烦啦,主要是学会这种设计思想就可以了。

源码如下

5、Memento

  1. /**
  2. * 备忘录
  3. * @author suibibk.com
  4. */
  5. public class Memento {
  6. private int level;//游戏等级
  7. private int score;//分数
  8. public Memento(int level, int score) {
  9. super();
  10. this.level = level;
  11. this.score = score;
  12. }
  13. public int getLevel() {
  14. return level;
  15. }
  16. public void setLevel(int level) {
  17. this.level = level;
  18. }
  19. public int getScore() {
  20. return score;
  21. }
  22. public void setScore(int score) {
  23. this.score = score;
  24. }
  25. }

6、User

  1. /**
  2. * 用户信息
  3. * @author suibibk.com
  4. */
  5. public class User {
  6. private int level;//用户等级
  7. private int score;//分数
  8. private String username;//用户游戏名
  9. public int getLevel() {
  10. return level;
  11. }
  12. public void setLevel(int level) {
  13. this.level = level;
  14. }
  15. public int getScore() {
  16. return score;
  17. }
  18. public void setScore(int score) {
  19. this.score = score;
  20. }
  21. public String getUsername() {
  22. return username;
  23. }
  24. public void setUsername(String username) {
  25. this.username = username;
  26. }
  27. public Memento createMemento() {
  28. return new Memento(level,score);
  29. }
  30. }

7、Manager

  1. /**
  2. * 游戏管理者 没有修改备忘录的权限
  3. * @author suibibk.com
  4. */
  5. public class Manager {
  6. private Memento memento;
  7. public Memento getMemento() {
  8. return memento;
  9. }
  10. public void setMemento(Memento memento) {
  11. this.memento = memento;
  12. }
  13. }

8、Test

  1. public class Test {
  2. public static void main(String[] args) {
  3. Manager manager = new Manager();
  4. System.out.println("用户注册游戏");
  5. User user = new User();
  6. user.setLevel(3);
  7. user.setScore(20);
  8. user.setUsername("林蛋黄");
  9. System.out.println("用户修炼后游戏的等级为:"+user.getLevel()+";游戏的分数为:"+user.getScore());
  10. System.out.println("先存档");
  11. manager.setMemento(user.createMemento());
  12. user.setLevel(10);
  13. user.setScore(23);
  14. System.out.println("用户继续修炼后游戏的等级为:"+user.getLevel()+";游戏的分数为:"+user.getScore());
  15. user.setLevel(0);
  16. user.setScore(0);
  17. System.out.println("服务器崩溃了,用户的等级和分数清零等级为:"+user.getLevel()+";游戏的分数为:"+user.getScore());
  18. System.out.println("读档");
  19. Memento m = manager.getMemento();
  20. user.setLevel(m.getLevel());
  21. user.setScore(m.getScore());
  22. System.out.println("读档后等级为:"+user.getLevel()+";游戏的分数为:"+user.getScore());
  23. }
  24. }

运行输出结果如下:

  1. 用户注册游戏
  2. 用户修炼后游戏的等级为:3;游戏的分数为:20
  3. 先存档
  4. 用户继续修炼后游戏的等级为:10;游戏的分数为:23
  5. 服务器崩溃了,用户的等级和分数清零等级为:0;游戏的分数为:0
  6. 读档
  7. 读档后等级为:3;游戏的分数为:20

可以看到完美的实现了读档存档的效果。

9、优缺点

优点

1、给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。
2、实现了信息的封装,使得用户不需要关心状态的保存细节。

缺点

消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。

总结

还是很容易的也很实用的,相信看上面的UML和例子都很容易理解的。

 425

啊!这个可能是世界上最丑的留言输入框功能~


当然,也是最丑的留言列表

有疑问发邮件到 : suibibk@qq.com 侵权立删
Copyright : 个人随笔   备案号 : 粤ICP备18099399号-2