本文源码:GitHub·点这里 || GitEE·点这里

一、生活场景

1、场景描述

常见的视频播放软件都具备这样一个功能:假设在播放视频西游记,如果这时候切换播放视频红楼梦,当再次切回播放西游记时,视频会从上次切走的时间点继续播放。下面基于备忘录设计模式来描述该场景流程。

2、场景图解

3、代码实现

  1. public class C01_InScene {
  2. public static void main(String[] args) {
  3. Record record = new Record() ;
  4. Player player = new Player() ;
  5. PlayData pd1 = new PlayData("西游记","19:19") ;
  6. PlayData pd2 = new PlayData("红楼梦","29:19") ;
  7. player.setPlayData(pd1);
  8. player.saveProgress() ;
  9. System.out.println("正在播放:"+
  10. player.getPlayData().getVideoName()+":"+
  11. player.getPlayData().getPlayTime());
  12. record.put(new Progress(pd1));
  13. System.out.println("===切换播放视频===");
  14. player.setPlayData(pd2);
  15. player.saveProgress() ;
  16. System.out.println("正在播放:"+
  17. player.getPlayData().getVideoName()+":"+
  18. player.getPlayData().getPlayTime());
  19. record.put(new Progress(pd1));
  20. System.out.println("===切回上个视频===");
  21. player.resumeProgress(record.get(pd1.getVideoName()));
  22. System.out.println("正在播放:"+
  23. player.getPlayData().getVideoName()+":"+
  24. player.getPlayData().getPlayTime());
  25. }
  26. }
  27. /**
  28. * 视频播放器
  29. */
  30. class Player {
  31. private PlayData playData ;
  32. public PlayData getPlayData() {
  33. return playData;
  34. }
  35. public void setPlayData(PlayData playData) {
  36. this.playData = playData;
  37. }
  38. public Progress saveProgress (){
  39. return new Progress(playData) ;
  40. }
  41. public void resumeProgress (Progress progress){
  42. playData = progress.getPlayData() ;
  43. }
  44. }
  45. /**
  46. * 播放进度
  47. */
  48. class Progress {
  49. private PlayData playData ;
  50. public Progress (PlayData playData){
  51. this.playData = playData ;
  52. }
  53. public PlayData getPlayData() {
  54. return playData ;
  55. }
  56. }
  57. /**
  58. * 播放记录
  59. */
  60. class Record {
  61. private Map<String,Progress> dataMap = new HashMap<>() ;
  62. public void put (Progress progress){
  63. dataMap.put(progress.getPlayData().getVideoName(),progress) ;
  64. }
  65. public Progress get (String videoName){
  66. return dataMap.get(videoName) ;
  67. }
  68. }
  69. /**
  70. * 播放状态描述
  71. */
  72. class PlayData {
  73. private String videoName ;
  74. private String playTime ;
  75. public PlayData(String videoName, String playTime) {
  76. this.videoName = videoName;
  77. this.playTime = playTime;
  78. }
  79. public String getVideoName() {
  80. return videoName;
  81. }
  82. public void setVideoName(String videoName) {
  83. this.videoName = videoName;
  84. }
  85. public String getPlayTime() {
  86. return playTime;
  87. }
  88. public void setPlayTime(String playTime) {
  89. this.playTime = playTime;
  90. }
  91. }

执行效果:

  1. 正在播放:西游记:19:19
  2. ===切换播放视频===
  3. 正在播放:红楼梦:29:19
  4. ===切回上个视频===
  5. 正在播放:西游记:19:19

二、备忘录模式

1、基础概念

备忘录模式属于行为型模式,其用意在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。后续可将该对象恢复到原先保存的状态。备忘录对象主要用来记录一个对象的某种状态,或者某些数据,当要做回退时,可以从备忘录对象里获取原来的数据进行恢复操作。

2、模式图解

3、核心角色

  • 备忘录角色

负责保存对象状态的记录,即Originator内部状态。

  • 发起人角色

创建一个含有当前的内部状态的备忘录对象,用来保存状态。

  • 守护者对象

提供合理的方式,负责保存多个备忘录对象。

4、源码实现

  1. public class C02_Memento {
  2. public static void main(String[] args) {
  3. Originator originator = new Originator();
  4. Caretaker caretaker = new Caretaker();
  5. originator.setState("状态1:State01");
  6. caretaker.add(originator.saveStateMemento());
  7. originator.setState("状态2:State02");
  8. caretaker.add(originator.saveStateMemento());
  9. System.out.println("当前的状态是 =" + originator.getState());
  10. // 恢复状态
  11. originator.getStateFromMemento(caretaker.get(0));
  12. System.out.println("当前的状态是 =" + originator.getState());
  13. }
  14. }
  15. /**
  16. * 守护者对象
  17. */
  18. class Caretaker {
  19. private List<Memento> mementoList = new ArrayList<>();
  20. public void add(Memento memento) {
  21. mementoList.add(memento);
  22. }
  23. public Memento get (int index) {
  24. return mementoList.get(index);
  25. }
  26. }
  27. /**
  28. * 备忘录角色
  29. */
  30. class Memento {
  31. private String state;
  32. public Memento(String state) {
  33. super();
  34. this.state = state;
  35. }
  36. public String getState() {
  37. return state;
  38. }
  39. }
  40. /**
  41. * 发起人角色
  42. */
  43. class Originator {
  44. private String state;
  45. public String getState() {
  46. return state;
  47. }
  48. public void setState(String state) {
  49. this.state = state;
  50. }
  51. public Memento saveStateMemento() {
  52. return new Memento(state);
  53. }
  54. public void getStateFromMemento(Memento memento) {
  55. state = memento.getState();
  56. }
  57. }

三、模式总结

1、优缺点描述

备忘录模式提供一种可以恢复状态的机制,实现状态的封装,能够比较方便地回到某个历史的状态;常常与命令模式和迭代器模式一同使用。如果类的成员变量过多,会占用比较大的内存资源,为了节约内存,备忘录模式可以和原型模式配合使用。

2、应用场景

  • 浏览器的前进和回退;
  • 数据库备份与还原;
  • 编辑器Ctrl+Z撤销;
  • 虚拟机生成快照与恢复;
  • Git版本管理,代码的提交和回滚。

四、源代码地址

  1. GitHub·地址
  2. https://github.com/cicadasmile/model-arithmetic-parent
  3. GitEE·地址
  4. https://gitee.com/cicadasmile/model-arithmetic-parent

Java描述设计模式(24):备忘录模式的更多相关文章

  1. 再起航,我的学习笔记之JavaScript设计模式24(备忘录模式)

    备忘录模式 概念介绍 备忘录模式(Memento): 在不破坏对象的封装性的前提下,在对象之外捕获并保存该对象内部的状态以便日后对象使用或者对象恢复到以前的某个状态. 简易分页 在一般情况下我们需要做 ...

  2. 折腾Java设计模式之备忘录模式

    原文地址:折腾Java设计模式之备忘录模式 备忘录模式 Without violating encapsulation, capture and externalize an object's int ...

  3. 乐在其中设计模式(C#) - 备忘录模式(Memento Pattern)

    原文:乐在其中设计模式(C#) - 备忘录模式(Memento Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 备忘录模式(Memento Pattern) 作者:webabc ...

  4. C#设计模式:备忘录模式(Memento Pattern)

    一,C#设计模式:备忘录模式(Memento Pattern) 1.发起人角色(Originator):记录当前时刻的内部状态,负责创建和恢复备忘录数据.负责创建一个备忘录Memento,用以记录当前 ...

  5. js设计模式——7.备忘录模式

    js设计模式——7.备忘录模式 /*js设计模式——备忘录模式*/ // 备忘类 class Memento { constructor(content) { this.content = conte ...

  6. java设计模式之备忘录模式

    备忘录模式 备忘录模式是一种软件设计模式:在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到原先保存的状态.一听到备忘录这个字的时候想起了小小时打的游 ...

  7. java设计模式9.备忘录模式、访问者模式、调停者模式

    备忘录模式 备忘录模式又叫快照模式,备忘录对象是一个用来存储另外一个对象内部状态快照的对象.备忘录的用意是在不破坏封装的条件下,将一个对象的状态捕捉,并外部化存储起来,从而可以在将来合适的时候把这个对 ...

  8. Java设计模式应用——备忘录模式

    备忘录模式主要用于存档.游戏中我们打boss前总会存档,如果打boss失败,则读取存档,重新挑战boss. 可以看出来,备忘录模式一般包括如下数据结构 1. 存档文件:用于恢复备份场景的必要数据: 2 ...

  9. 19.java设计模式之备忘录模式

    基本需求 游戏的角色有攻击力和防御力,在大战Boss之前保存自身的状态(攻击力和防御力),当大战Boss之后攻击力和防御力下降,从备忘录对象恢复到大战前的状态 传统方案 一个对象,就对应一个保存对象状 ...

随机推荐

  1. Redis备忘(一)

    hash: 渐进式rehash:同时查询新旧两个hash,然后在后续定时任务以及hash的子指令中,循序渐进将旧的迁移到新的hash表 Redis应用: 1.分布式锁: 实现1:setnx+expir ...

  2. vscode发博客插件更新v0.1.0(可能会相对好用点吧)

    距离上一次编写这个vscode在博客园发博客的插件已经过去好久了,那个时候vscode插件的功能也没有那么强大,期间有人提出问题来,也有人提出建议来,我一直没有抽出时间来维护,深感抱歉,直到有人加到我 ...

  3. Java多线程编程(七)线程状态、线程组与异常处理

    一.线程的状态 线程对象在不同的运行时期有不同的状态,状态信息就存在于State枚举类中. 调用与线程有关的方法后,会进入不同的线程状态,这些状态之间某些是可双向切换的,比如WAITING和RUNNI ...

  4. 游图邦YOTUBANG是如何搭建生态系统的?

    现在的我们最关心的一个问题就是任何一个行业,如果没有办法很好的落地,就算描绘的非常美好,那也只是空中楼阁.昙花一现而已,它无法实现长久的一个发展.互联网时代呢,就是一个流量为王的一个时代,谁拥有庞大的 ...

  5. Linux 如何创建或删除以横杠(-)开头的文件或目录

    小测试: [root@test test]# ls [root@test test]# touch -abc touch: invalid option -- 'b' Try `touch --hel ...

  6. MIT线性代数:19.行列式和代数余子式

  7. Visual Studio Online 的 FAQ:iPad 支持、自托管环境、Web 版 VS Code、Azure 账号等

    北京时间 2019 年 11 月 4 日,在 Microsoft Ignite 2019 大会上,微软正式发布了 Visual Studio Online 公开预览版!发布之后,开发者们都为之振奋.同 ...

  8. zookeeper集群搭建2.7

    http://blog.csdn.net/uq_jin/article/details/51513307

  9. Android so 文件

    要点 不同的 CPU 架构需要不同的 so 文件 NDK平台不是后向兼容的,而是前向兼容的. ABI 的概念,每一个 Cpu架构对应一个 ABI(Application Binary Interfac ...

  10. ElasticSearch(二):文档的基本CRUD与批量操作

    ElasticSearch(二):文档的基本CRUD与批量操作 学习课程链接<Elasticsearch核心技术与实战> Create 文档 支持自动生成文档_id和指定文档_id两种方式 ...