备忘录模式定义
定义:在不破坏封闭的前提下,获取一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可以将该对象恢复到原先保存的状态。 (该模式是一个行为模式)
关键点:不破坏封闭、将状态保存在对象之外
解析:该模式将对象的状态(信息)存储在另一个类对象中,将数据源和备份数据进行了分离。
备忘录模式的相关角色
参与角色 | 功能 |
---|---|
发起人(Originator) | 需要进行状态保存的对象,在内部拥有创建备忘录和恢复数据的方法 |
备忘录(Memento) | 保存发起人状态(信息) |
管理者(Caretaker) | 持有一个备忘录对象的引用,对外部提供一个获取和存储备忘录角色的接口,不提供其他关于备忘录角色的相关方法 |
关于相关角色的介绍:使用该模式的一个流程为Originator创建一个Memento对象,并将需要保存的状态存放于该对象中,然后将该对象作为一个返回值返回,获取返回的Memento对象工作由Caretaker对象来完成,调用Caretaker对象相应方法将获取的Memento对象保存在自己内部的Memento引用中,如果后期需要使用到备份中的数据时,同样有Caretaker对象返回自己以前保存的Memento对象给Originator对象,然后Originator对象在自己的内部使用备份数据来恢复自己的状态。(是的没错就是这样)
备忘录模式UML
案例引入
就拿游戏来说吧(想来想去还是想不出一个不是游戏又比较好的例子,噗),我们需要使用备忘录模式完成用户退出游戏的时候自动实现保存该用户当前的角色属性信息,然后在重新用户登录的时候,自动恢复到上次退出时的状态。
案例分析
下面我们来一起分析三个角色分别是什么,该如何去实现。
发起人(Originator):游戏角色,我们需要创建一个GameCharacter类,该类中我们需要有一个创建备份的方法,一个恢复数据的方法,以及一些与角色相关的属性变量。
备忘录(Memento):存储角色属性,需要创建一个类Memento,该类拥有与游戏角色属性相关的变量,用于存储发起人的相关信息。
管理者(Caretaker):管理备忘录的,在该案例中我们需要创建一个Caretaker类,该类拥有一个Memento对象的引用、一个从外部获取Memento对象并将该对象保存在自己类体内部的方法和一个返回自己内部存储的Memento对象的方法。
案例实现
发起人代码:
package memento.pattern;
/**
* @Introduction 该类是发起者角色,内部拥有创建备忘录和恢复数据的方法
*/
public class GameCharacter {
private String roleName;
private int level;
//构造方法
public GameCharacter(String name,int level) {
this.roleName=name;
this.level=level;
}
//创建备忘录角色
public Memeto saveGame() {
Memeto tem=new Memeto();
tem.setValue(roleName, level);
return tem;
}
//恢复数据
public void recover(Memeto memeto) {
this.level=memeto.getLevel();
this.roleName=memeto.getName();
}
}
备忘录角色代码:
package memento.pattern;
/**
* @Introduction 该类是备忘录角色
*/
public class Memeto {
private String roleName; //游戏角色名称
private int level; //等级
//设置相关信息的方法
public void setValue(String rolename,int levell) {
this.roleName=rolename;
this.level=levell;
}
public String getName() {
return this.roleName;
}
public int getLevel() {
return this.level;
}
}
管理者代码:
package memento.pattern;
/**
* @Introduciton 该类是管理者角色。
*/
public class Caretaker {
private Memeto memento;
//用于获取外部的备忘录对象
public void saveMemento(Memeto memento) {
this.memento=memento;
}
//提供保存的备忘录
public Memeto getMemento() {
return this.memento;
}
}
用户退出和登陆模拟代码:
package memento.pattern;
/**
* @Introduction 该类是模拟用户退出游戏和登陆游戏的相关操作
*/
public class Mian {
public static void main(String[] args) {
GameCharacter role=new GameCharacter("请叫我帮主",9999); //要保存的游戏角色
Caretaker manager=new Caretaker();
//退出游戏
manager.saveMemento(role.saveGame()); //创建一个备忘录,存放在管理者中
//登陆游戏
role.recover(manager.getMemento()); //将数据恢复到游戏角色中
}
}
备忘录模式优缺点
优点:
- 实现了数据源和备份数据的分离,同时对数据提供了较好的保护(我们将数据的传递在类体中实现)
- 实现了单一职责原则。
缺点:
如果发起人角色要存储所有数据同时数据量比较大,使用该种模式将会消耗比较大的系统资源。