备忘录模式
介绍
- 是一种行为模式
- 用于保存对象当前状态,并在之后恢复到此状态(后悔药)
- 需要保证被保存的对象状态不能被外部访问,保证内部完整性,不向外透露
定义
- 在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便恢复到原先保存的状态
使用场景
需要保存一个对象在某一个时刻的状态或者部分状态
如果用一个接口来让其他对象的到这些状态,将会暴露这个对象的实现细节并破坏对象的的封装性,一个对象不希望外界直接访问其内部状态,通过中间对象可以间接访问其内部状态
UML
说明
Originator:负责创建一个备忘录,可以记录、恢复自身的内部状态。同事还可以根据需要决定Memento存储自身的那些状态
Mement:备忘录角色,用于存储Originator的内部状态,并且可以防止Originator以外的对象访问Memento
Caretaker: 负责存储备忘录,不能对备忘录的内容进行操作和访问,只能够将备忘录传递给其他对象
简单实现
1.备忘录类,用于记录游戏需要记录的详细信息
/**
* 备忘录类
*/
public class Memoto {
public int mCheckpoint;
public int mLifeValue;
public String mWeapon;
@Override
public String toString() {
return "Memoto [mCheckpoint="+mCheckpoint+
" mLifeValue"+mLifeValue+
" mWeapon"+mWeapon+"]";
}
}复制代码
2.创建游戏类(Originator),实现游戏基本逻辑,其内部可以实现备忘录的创建以及获取,但是不实现存储以及恢复的逻辑
/*
* 使命召唤游戏演戏(Originator)
*/
public class CallOfDuty {
private int mCheckpoint = 1;
private int mLifeValue = 100;
private String mWeapon = "沙漠之鹰";
public void play(){
System.out.println("打游戏:" + String.format("第%d关", mCheckpoint) + "奋战杀敌中");
mLifeValue -=10;
System.out.println("进度升级了");
mCheckpoint++;
System.out.println("到达"+String.format("第%d关", mCheckpoint));
}
public void quit(){
System.out.println("---------------------");
System.out.println("退出前的属性:"+this.toString());
System.out.println("退出游戏");
System.out.println("---------------------");
}
//创建备忘录
public Memoto createMemoto(){
Memoto memoto = new Memoto();
memoto.mCheckpoint = mCheckpoint;
memoto.mLifeValue = mLifeValue;
memoto.mWeapon = mWeapon;
return memoto;
}
public void restore(Memoto memoto){
this.mCheckpoint = memoto.mCheckpoint;
this.mLifeValue = memoto.mLifeValue;
this.mWeapon = memoto.mWeapon;
System.out.println("恢复后的游戏属性:"+this.toString());
}
@Override
public String toString() {
return "CallOfDuty [mCheckpoint="+mCheckpoint+
" mLifeValue"+mLifeValue+
" mWeapon"+mWeapon+"]";
}
}复制代码
3.Caretaker类的创建,实现游戏进度的存档以及恢复逻辑,但是不对实际的游戏数据进行操作
/**
* 负责管理Memoto
*/
public class Caretaker {
//备忘录
Memoto memoto;
//存档
public void archive(Memoto memoto){
this.memoto = memoto;
}
//获取存档
public Memoto getMemoto(){
return memoto;
}
}复制代码
4.Main函数的实现
public class Main {
public static void main(String[] args) {
//构建游戏对象
CallOfDuty callOfDuty = new CallOfDuty();
//开始游戏
callOfDuty.play();
//构建caretaker,用于游戏存档
Caretaker caretaker = new Caretaker();
//通过游戏本身创建备忘录,caretaker执行存档操作
caretaker.archive(callOfDuty.createMemoto());
//退出游戏
callOfDuty.quit();
//重新开启游戏,并通过caretaker恢复游戏进度
CallOfDuty callOfDuty1 = new CallOfDuty();
callOfDuty1.restore(caretaker.getMemoto());
}
}复制代码
5.运行结果
打游戏:第1关奋战杀敌中
进度升级了
到达第2关
---------------------
退出前的属性:CallOfDuty [mCheckpoint=2 mLifeValue90 mWeapon沙漠之鹰]
退出游戏
---------------------
恢复后的游戏属性:CallOfDuty [mCheckpoint=2 mLifeValue90 mWeapon沙漠之鹰]复制代码
- 总结:CallOfDuty在这里是Origintor角色,也就是需要存储数据的对象,这里并没有直接存储CallOfDuty对象,而是通过Memoto对CallOfDuty对象的数据进行存储,然后在存储Memoto对象,最终对Memoto对象的存取操作交给Caretaker对象。在整个过程中,对外屏蔽了对CallOfDuty角色的直接访问,满足对象状态存取功能的同时也是的该模块的结构保持清晰、整洁。