Java描述设计模式(24):备忘录模式
本文源码:GitHub·点这里 || GitEE·点这里
一、生活场景
1、场景描述
常见的视频播放软件都具备这样一个功能:假设在播放视频西游记,如果这时候切换播放视频红楼梦,当再次切回播放西游记时,视频会从上次切走的时间点继续播放。下面基于备忘录设计模式来描述该场景流程。
2、场景图解

3、代码实现
public class C01_InScene {
public static void main(String[] args) {
Record record = new Record() ;
Player player = new Player() ;
PlayData pd1 = new PlayData("西游记","19:19") ;
PlayData pd2 = new PlayData("红楼梦","29:19") ;
player.setPlayData(pd1);
player.saveProgress() ;
System.out.println("正在播放:"+
player.getPlayData().getVideoName()+":"+
player.getPlayData().getPlayTime());
record.put(new Progress(pd1));
System.out.println("===切换播放视频===");
player.setPlayData(pd2);
player.saveProgress() ;
System.out.println("正在播放:"+
player.getPlayData().getVideoName()+":"+
player.getPlayData().getPlayTime());
record.put(new Progress(pd1));
System.out.println("===切回上个视频===");
player.resumeProgress(record.get(pd1.getVideoName()));
System.out.println("正在播放:"+
player.getPlayData().getVideoName()+":"+
player.getPlayData().getPlayTime());
}
}
/**
* 视频播放器
*/
class Player {
private PlayData playData ;
public PlayData getPlayData() {
return playData;
}
public void setPlayData(PlayData playData) {
this.playData = playData;
}
public Progress saveProgress (){
return new Progress(playData) ;
}
public void resumeProgress (Progress progress){
playData = progress.getPlayData() ;
}
}
/**
* 播放进度
*/
class Progress {
private PlayData playData ;
public Progress (PlayData playData){
this.playData = playData ;
}
public PlayData getPlayData() {
return playData ;
}
}
/**
* 播放记录
*/
class Record {
private Map<String,Progress> dataMap = new HashMap<>() ;
public void put (Progress progress){
dataMap.put(progress.getPlayData().getVideoName(),progress) ;
}
public Progress get (String videoName){
return dataMap.get(videoName) ;
}
}
/**
* 播放状态描述
*/
class PlayData {
private String videoName ;
private String playTime ;
public PlayData(String videoName, String playTime) {
this.videoName = videoName;
this.playTime = playTime;
}
public String getVideoName() {
return videoName;
}
public void setVideoName(String videoName) {
this.videoName = videoName;
}
public String getPlayTime() {
return playTime;
}
public void setPlayTime(String playTime) {
this.playTime = playTime;
}
}
执行效果:
正在播放:西游记:19:19
===切换播放视频===
正在播放:红楼梦:29:19
===切回上个视频===
正在播放:西游记:19:19
二、备忘录模式
1、基础概念
备忘录模式属于行为型模式,其用意在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。后续可将该对象恢复到原先保存的状态。备忘录对象主要用来记录一个对象的某种状态,或者某些数据,当要做回退时,可以从备忘录对象里获取原来的数据进行恢复操作。
2、模式图解

3、核心角色
- 备忘录角色
负责保存对象状态的记录,即Originator内部状态。
- 发起人角色
创建一个含有当前的内部状态的备忘录对象,用来保存状态。
- 守护者对象
提供合理的方式,负责保存多个备忘录对象。
4、源码实现
public class C02_Memento {
public static void main(String[] args) {
Originator originator = new Originator();
Caretaker caretaker = new Caretaker();
originator.setState("状态1:State01");
caretaker.add(originator.saveStateMemento());
originator.setState("状态2:State02");
caretaker.add(originator.saveStateMemento());
System.out.println("当前的状态是 =" + originator.getState());
// 恢复状态
originator.getStateFromMemento(caretaker.get(0));
System.out.println("当前的状态是 =" + originator.getState());
}
}
/**
* 守护者对象
*/
class Caretaker {
private List<Memento> mementoList = new ArrayList<>();
public void add(Memento memento) {
mementoList.add(memento);
}
public Memento get (int index) {
return mementoList.get(index);
}
}
/**
* 备忘录角色
*/
class Memento {
private String state;
public Memento(String state) {
super();
this.state = state;
}
public String getState() {
return state;
}
}
/**
* 发起人角色
*/
class Originator {
private String state;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public Memento saveStateMemento() {
return new Memento(state);
}
public void getStateFromMemento(Memento memento) {
state = memento.getState();
}
}
三、模式总结
1、优缺点描述
备忘录模式提供一种可以恢复状态的机制,实现状态的封装,能够比较方便地回到某个历史的状态;常常与命令模式和迭代器模式一同使用。如果类的成员变量过多,会占用比较大的内存资源,为了节约内存,备忘录模式可以和原型模式配合使用。
2、应用场景
- 浏览器的前进和回退;
- 数据库备份与还原;
- 编辑器
Ctrl+Z撤销; - 虚拟机生成快照与恢复;
- Git版本管理,代码的提交和回滚。
四、源代码地址
GitHub·地址
https://github.com/cicadasmile/model-arithmetic-parent
GitEE·地址
https://gitee.com/cicadasmile/model-arithmetic-parent

Java描述设计模式(24):备忘录模式的更多相关文章
- 再起航,我的学习笔记之JavaScript设计模式24(备忘录模式)
备忘录模式 概念介绍 备忘录模式(Memento): 在不破坏对象的封装性的前提下,在对象之外捕获并保存该对象内部的状态以便日后对象使用或者对象恢复到以前的某个状态. 简易分页 在一般情况下我们需要做 ...
- 折腾Java设计模式之备忘录模式
原文地址:折腾Java设计模式之备忘录模式 备忘录模式 Without violating encapsulation, capture and externalize an object's int ...
- 乐在其中设计模式(C#) - 备忘录模式(Memento Pattern)
原文:乐在其中设计模式(C#) - 备忘录模式(Memento Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 备忘录模式(Memento Pattern) 作者:webabc ...
- C#设计模式:备忘录模式(Memento Pattern)
一,C#设计模式:备忘录模式(Memento Pattern) 1.发起人角色(Originator):记录当前时刻的内部状态,负责创建和恢复备忘录数据.负责创建一个备忘录Memento,用以记录当前 ...
- js设计模式——7.备忘录模式
js设计模式——7.备忘录模式 /*js设计模式——备忘录模式*/ // 备忘类 class Memento { constructor(content) { this.content = conte ...
- java设计模式之备忘录模式
备忘录模式 备忘录模式是一种软件设计模式:在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到原先保存的状态.一听到备忘录这个字的时候想起了小小时打的游 ...
- java设计模式9.备忘录模式、访问者模式、调停者模式
备忘录模式 备忘录模式又叫快照模式,备忘录对象是一个用来存储另外一个对象内部状态快照的对象.备忘录的用意是在不破坏封装的条件下,将一个对象的状态捕捉,并外部化存储起来,从而可以在将来合适的时候把这个对 ...
- Java设计模式应用——备忘录模式
备忘录模式主要用于存档.游戏中我们打boss前总会存档,如果打boss失败,则读取存档,重新挑战boss. 可以看出来,备忘录模式一般包括如下数据结构 1. 存档文件:用于恢复备份场景的必要数据: 2 ...
- 19.java设计模式之备忘录模式
基本需求 游戏的角色有攻击力和防御力,在大战Boss之前保存自身的状态(攻击力和防御力),当大战Boss之后攻击力和防御力下降,从备忘录对象恢复到大战前的状态 传统方案 一个对象,就对应一个保存对象状 ...
随机推荐
- django-URL重定向(八)
HttpResponseRedirect()不常用 redirect(to,permanent=False,*args,**kwargs) to:指重定向的位置,可以是视图,也可以是url地址,也可以 ...
- 匹马行天下之思维决定高度篇——道道道,学习Java之道
致Java星球的程序员兄弟们的一封信 亲爱的Java星球的程序员兄弟们: 你们好!我是来自地球的一名Java程序员,首先我代表地球人对贵星球的高司令来到地球传授Java语言,造福了全人类,造福了整个地 ...
- Vue引入插件
引入Element ui 1.在当前目录下,运行:npm i element-ui -S 2.在src/main.js中添加代码 import ElementUI from 'element-ui' ...
- String 和StringBuffe StringBuilder 的区别
1.可变性:String不可变(适用于做HashMap的键),StringBuffer和StringBuilder可变 2.性能角度:,String在new的时候,会在常量池中开辟空间,比较耗费内存, ...
- 在VMware下进行的CentOS7操作系统虚拟机的安装
一.VMware虚拟机的安装 首先你需要拥有一款软件VMware,这是一款虚拟机安装软件.Vmware比起Vbox收费较贵,占用资源大,但是拥有大量的资源以及拥有克隆技术,适合新手学习使用,较为专业. ...
- *args和**kwargs的作用
∗args的作用: *的作用有2个 打包参数(pack)和拆分参数(unpack) 函数接受实参时,按顺序分配给函数形参,如果遇到带∗的形参,那么就把还未分配出去的实参以元组形式打包(pack),分配 ...
- 口胡题fr
T1五种贡献恶心的要死.$1.grand$$2.father$$3.brother$$4.son$$5.grandson$我们选择维护三个量.1.儿子和,$sx$2.孙子和,$gsx$3.自己的值,$ ...
- (25)ASP.NET Core EF查询(复杂查询运算符、原生SQL查询、异步查询)
1.复杂查询运算符 在生产场景中,我们经常用到LINQ运算符进行查询获取数据,现在我们就来了解下生产场景经常出现几种复杂查询运算符. 1.1联接(INNER JOIN) 借助LINQ Join运算符, ...
- 8.1 NOIP模拟11
8.1 NOIP模拟 11 今天上午返校之后,颓了一会,然后下午就开始考试,中午睡着了,然后刚开始考试的时候就困的一匹,我一看T1,woc,这不是之前线段树专题的题啊,和那道题差不多,所以我..... ...
- python入门递归之汉诺塔
def hani(n,x,y,z): if n == 1 : print(x ,"-->",z) else: hani(n-1,x,z,y)#将n-1个盘子从x移到y pri ...