简述-备忘录模式
介绍
备忘录顾名思义就是存储,方便下次使用,达到后悔药的作用。
定义
在不破坏封闭的情况下,捕获对象内部状态,在该对象之外保存这个状态,在需要的时候可以进行恢复。
UML
- Originator (源头对象): 负责创建一个备忘录,可以记录、恢复自身的内部状态。同时Originator还可以根据需要决定Memnento存储自身的哪些内部状态。
- Memento(存储状态信息的对象): 备忘录角色,用于存储Originator的内部状态,并且可以防止Originator以外的对象访问Memento。
- Caretaker(操作的对象):负责存储备忘录,不能对备忘录的内容进行操作和访问,只能够将备忘录传递给其他对象。
使用场景
- 需要保存对象某一时刻状态
- 如果用一个接口来让其他对象得到这些状态会暴露实现细节的封装,一个对象不希望外界直接访问其内部状态,通过中间对象(存储状态的对象)可以间接访问其内部状态。
事例
比如咱们在查看一段视频,在退出后再进入,想接着上一次查看的视频点继续看,那么就需存储来支持了。
- 建立保存的数据
/**
* 备忘信息
*/
public class MemoInfo {
/**
* 播放点
*/
private int position;
public MemoInfo(int position) {
this.position = position;
}
/**
* 获取
* @return
*/
public int getPosition() {
return position;
}
/**
* 设置
* @param position
*/
public void setPosition(int position) {
this.position = position;
}
}
- 建立使用数据的实体对象
/**
* 源信息对象
* 1. 提供创建备忘对象
* 2. 提供接收备忘对象恢复信息
*/
public interface IOrigin {
/**
* 恢复
* @param memoInfo
*/
void restorMemo(MemoInfo memoInfo);
/**
* 创建
* @return
*/
MemoInfo createMemo();
}
/**
* 源对象实现
*/
public class PlayOrigin implements IOrigin {
/**
* 播放点
*/
private int position;
public void playInfo() {
System.out.println("播放点:" + position);
//播放后前进一个点
position++;
}
/**
* 接收存储对象恢复当前播放点
* @param memoInfo
*/
@Override
public void restorMemo(MemoInfo memoInfo) {
this.position = memoInfo.getPosition();
}
/**
* 存储当前播放点返回
* @return 存储对象
*/
@Override
public MemoInfo createMemo() {
return new MemoInfo(position);
}
}
- 建立存储者
/**
* 看管者,用于保存存储信息,和获取存储信息
*/
public class Caretaker {
private MemoInfo memoInfo;
/**
* 获取存储信息
* @return 存储信息
*/
public MemoInfo getMemoInfo() {
return memoInfo != null ? memoInfo : new MemoInfo(0);
}
/**
* 保存存储信息
* @param memoInfo 要存储的信息
*/
public void saveMemoInfo(MemoInfo memoInfo) {
this.memoInfo = memoInfo;
}
}
- 测试类:
public static void main(String[] arg) {
System.out.println("第一次播放");
PlayOrigin playOrigin = new PlayOrigin();
playOrigin.playInfo();
//创建存储信息,并存到看管者那里
MemoInfo memo = playOrigin.createMemo();
Caretaker caretaker = new Caretaker();
caretaker.saveMemoInfo(memo);
playOrigin.quit();
System.out.println("再次播放");
//再次进行播放,从看管者那里拿去信息恢复
PlayOrigin playOrigin2 = new PlayOrigin();
playOrigin2.restorMemo(caretaker.getMemoInfo());
playOrigin2.playInfo();
}
- 输出:
第一次播放
播放点:0
收到存储消息
退出了
再次播放
播放点:1
可以看到输出,再第一次播放后前进了一个点,第二次就接着播放了,那么就达到了从存储拿出来的效果了。
总结:编码上通过状态信息的封装(originator被保存状态的类,Caretaker管理类,Memoto信息类),用户不需要关心状态的保存细节,这是这个模式的一个优点。思想是:存档可再用。像demo这样直接的保存方式,是会耗内存,另一种就是存文件的方式,也是达到这个存储再用的,根据实际情况考虑使用就好。