1 Memento Pattern 备忘录模式
目的:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态;
实现:客户不与备忘录类耦合,与备忘录管理类耦合,通过一个备忘录类专门存储对象状态。
1.并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态;
2.很多时候我们总是需要记录一个对象的内部状态,这样做的目的就是为了允许用户取消不确定或者错误的操作,能够恢复到他原先的状态,使得他有”后悔药”可吃。
2 实现
代码场景:西汉王朝继秦朝之后的大一统王朝,每年都在发生着大事,太史令司马迁负责将这些事件记录到史书中以供后世查看。
1.原发器角色是西汉王朝;
2.备忘录角色是历史事件;
3.负责人角色是司马迁。
因案例是真实历史事件,故不提供时光倒流的实现。
在使用该模式时可根据需要提供”后悔药”方法。
2.1 代码实现
原发器角色:西汉王朝
public class Han {
//事件
private String thing;
public String getThing() {
return thing;
}
public void setThing(String thing) {
this.thing = thing;
}
}
备忘录角色:历史事件
public class History {
private String thing;
public History(String thing) {
this.thing = thing;
}
public String getThing() {
return thing;
}
}
负责人角色:司马迁
public class SiMaQian {
private Map<String, History> historyMap = new HashMap<String, History>();
public void addHistoryList(String year, History history) {
historyMap.put(year, history);
}
public History getHistoryList(String year) {
if (historyMap.containsKey(year)) {
return historyMap.get(year);
}
return null;
}
}
2.2 涉及角色
在备忘录模式结构图中包含如下几个角色:
Originator(原发器):它是一个普通类,可以创建一个备忘录,并存储它的当前内部状态,也可以使用备忘录来恢复其内部状态,一般将需要保存内部状态的类设计为原发器。
Memento(备忘录):存储原发器的内部状态,根据原发器来决定保存哪些内部状态。备忘录的设计一般可以参考原发器的设计,根据实际需要确定备忘录类中的属性。需要注意的是,除了原发器本身与负责人类之外,备忘录对象不能直接供其他类使用,原发器的设计在不同的编程语言中实现机制会有所不同。
Caretaker(负责人):负责人又称为管理者,它负责保存备忘录,但是不能对备忘录的内容进行操作或检查。在负责人类中可以存储一个或多个备忘录对象,它只负责存储对象,而不能修改对象,也无须知道对象的实现细节。
2.3 调用
调用者:
public class Client {
public static void main(String[] args) {
// 大汉帝国
Han han = new Han();
// 汉武帝建元年间 司马到长安任太史令
System.out.println("汉武帝建元年间,司马到长安任太史令。");
SiMaQian sm = new SiMaQian();
// 公元前108年
han.setThing("天下大旱。");
History h = new History(han.getThing());
sm.addHistoryList("公元前108年", h);
// 公元前104年
han.setThing("汉朝历法改革,制定<<汉历>>。");
History h1 = new History(han.getThing());
sm.addHistoryList("公元前104年", h1);
// 公元前99年
han.setThing("李陵率步兵五千涉单于庭以寡击众,粮尽矢绝后,被迫投降。");
History h2 = new History(han.getThing());
sm.addHistoryList("公元前99年", h2);
System.out.println("公元前108年:" + sm.getHistoryList("公元前108年").getThing());
System.out.println("公元前104年:" + sm.getHistoryList("公元前108年").getThing());
System.out.println("公元前99年:" + sm.getHistoryList("公元前108年").getThing());
// 历史不可倒退 故无法回到过去
}
}
结果:
汉武帝建元年间,司马到长安任太史令。
公元前108年:天下大旱。
公元前104年:天下大旱。
公元前99年:天下大旱。
参考文献:
[ 1 ] 图解设计模式/(日)结城浩著;杨文轩译。–北京:人民邮电出版社,2017.1.
[ 2 ] 维基百科 设计模式
[ 3 ] 极客学院WIKI–设计模式.
[ 4 ] 菜鸟教程–设计模式.