设计模式-备忘录模式
概念
所谓备忘录模式就是在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。
优点
1、给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。
2、实现了信息的封装,使得用户不需要关心状态的保存细节。
缺点
消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。
使用场景
很多时候我们总是需要记录一个对象的内部状态,这样做的目的就是为了允许用户取消不确定或者错误的操作,能够恢复到他原先的状态,使得他有"后悔药"可吃。
角色
Memento 包含了要被恢复的对象的状态。
Originator 创建并在 Memento 对象中存储状态。
Caretaker 对象负责从 Memento 中恢复对象的状态。
案例描述
一个学生在看金庸武侠电子书,到做饭点保存进度,吃完饭恢复进度继续看
UML类图
代码解析UML类图
Memento 包含了要被恢复的对象的状态。
/** * 设计模式-备忘录模式-Memento * * 电子书备忘录 * * Created by laizhiyuan on 2017/6/12. */ public class EBookMemento { /** * 保存行数属性 */ private int rowNumber; public EBookMemento(int rowNumber) { this.rowNumber = rowNumber; } public int getRowNumber() { return rowNumber; } }
Originator 创建并在 Memento 对象中存储状态。
/** * 设计模式-备忘录模式-Originator * * 电子书 * * Created by laizhiyuan on 2017/6/12. */ public class EBookOriginator { /** * 行数 */ private int rowNumber; /** * 保存进度 * * @return */ public EBookMemento saveProgress(){ return new EBookMemento(this.rowNumber); } /** * 恢复进度 * * @param eBookMemento */ public void progress(EBookMemento eBookMemento){ setRowNumber(eBookMemento.getRowNumber()); } public int getRowNumber() { return rowNumber; } public void setRowNumber(int rowNumber) { this.rowNumber = rowNumber; } }
Caretaker 对象负责从 Memento 中恢复对象的状态。
/** * 设计模式-备忘录模式-Caretaker * * 管理电子书备忘录 * * Created by laizhiyuan on 2017/6/12. */ public class EBookCaretaker { private EBookMemento eBookMemento; public EBookMemento geteBookMemento() { return eBookMemento; } public void seteBookMemento(EBookMemento eBookMemento) { this.eBookMemento = eBookMemento; } }
测试
/** * 测试 * * Created by laizhiyuan on 2017/6/12. */ public class Main { public static void main(String[] args) { EBookOriginator eBook = new EBookOriginator(); /** * 早上八点开始看 */ int yema = 0; int time = 8; eBook.setRowNumber(yema); while (time < 11){ try { /** * 一小时十页 */ eBook.setRowNumber(eBook.getRowNumber() + 10); System.out.println("看书中....."); Thread.sleep(1000); System.out.println("过了一个小时"); time += 1; } catch (InterruptedException e) { e.printStackTrace(); } } EBookCaretaker caretaker = new EBookCaretaker(); caretaker.seteBookMemento(eBook.saveProgress()); System.out.println("当前页码:" + eBook.getRowNumber() + "\t当前时间:" + time + "点 \t 保存进度,准备做饭去"); try { Thread.sleep(2000); time += 2; eBook.progress(caretaker.geteBookMemento()); /** * 看小说都是好有精神的,都不用午休的 */ System.out.printf("吃完饭继续看书,恢复上次进度页码: " + eBook.getRowNumber()); } catch (InterruptedException e) { e.printStackTrace(); } } }