备忘录模式(Java实现,附带实例)
有的时候,我们可能要保存与对象状态有关的少量信息,以便将来把该对象恢复到它应有的状态。备忘录模式所提供的正是这个功能,它属于经典的 GoF(Gang of Four)设计模式。
备忘录(memento)让我们在不破坏封装的前提下,捕获对象的内部状态并将其交给外界,使得外界稍后可以将该对象恢复到制作备忘录时的样子。
备忘录模式向用户提供了一套功能,令其可以根据需求随时使用早前制作的备忘录,将对象恢复到想要的状态。
你可以让 Date 类的实例先指向某个特定的时间点,然后修改这个实例的状态,令其表示其他的时间点,最后再将其恢复到早前的那个时间点上(用 Date 表示日期与时间的时候,还可以根据历法和时区将同一个时刻表示成不同的形式)。
【实例】司机能够随时将空调的状态制作成备忘录,并根据某份备忘录把空调恢复到当时的状态。
【实例】每次保存状态都会形成一个标识码用于恢复对象状态。
【实例】AirConditionSystemOriginator 记录空调的状态,提供制作备忘录的功能,并把这份备忘录的序号返回给用户。

图 1 用UML类图来演示几个类
备忘录模式能够帮助程序执行撤销(undo)操作,或者令其状态退回到早前的某个时间点。该模式让我们能够清晰地实现这些功能,并将不同的逻辑划分开,使得程序的代码更容易维护。
备忘录(memento)让我们在不破坏封装的前提下,捕获对象的内部状态并将其交给外界,使得外界稍后可以将该对象恢复到制作备忘录时的样子。
备忘录模式向用户提供了一套功能,令其可以根据需求随时使用早前制作的备忘录,将对象恢复到想要的状态。
备忘录模式在JDK中的运用
Date 类就是备忘录模式的典型范例,它位于 java.base 模块的 java.util 包中。你可以让 Date 类的实例先指向某个特定的时间点,然后修改这个实例的状态,令其表示其他的时间点,最后再将其恢复到早前的那个时间点上(用 Date 表示日期与时间的时候,还可以根据历法和时区将同一个时刻表示成不同的形式)。
备忘录模式实例演示
我们以车里的空调为例。假设空调提供了多个挡位,用来调整驾驶室的温度,另外还提供记忆功能,让司机能够根据早前的某一份记录将挡位恢复到当时的状态(司机需要指出那份记录的序号),参见下面的实例。【实例】司机能够随时将空调的状态制作成备忘录,并根据某份备忘录把空调恢复到当时的状态。
public static void main(String[] args) { System.out.println("Memento Pattern, air-condition system"); var originator = new AirConditionSystemOriginator(); var careTaker = new AirConditionSystemCareTaker(); originator.setState("low"); var stateLow = originator.saveState(careTaker); originator.setState("medium"); var stateMedium = originator.saveState(careTaker); originator.setState("high"); var stateHigh = originator.saveState(careTaker); System.out.printf("\n\nCurrent Air-Condition System state:'%s'\n\n", originator.getState()); originator.restoreState(careTaker.getMemento(stateLow)); System.out.printf("\n\nRestored position:'%d', Air-Condition System state:'%s'\n\n", stateLow, originator.getState()); }程序输出结果如下:
Memento Pattern, air-condition system
Current Air-Condition System state:'high'
Restored position:'0', Air-Condition System state:'low'
【实例】每次保存状态都会形成一个标识码用于恢复对象状态。
final class AirConditionsSystemCareTaker { private final List<SystemMemento> memory = new ArrayList<>(); ... int add(SystemMemento m) { ... } SystemMemento getMemento(int i) { ... } }AirConditionSystemOriginator 类的实例负责把对象的当前状态创建成备忘录,还负责根据某份备忘录恢复对象的状态。用户通过该类的 saveState() 方法创建备忘录时,需要把它所返回的备忘录序号(也就是状态标识码)记住,因为稍后恢复状态时,需要通过这个序号从 AirConditionSystemCareTaker 里把相应的备忘录取出来,并交给 originator 的 restoreState() 方法去执行恢复(参见下面的实例)。
【实例】AirConditionSystemOriginator 记录空调的状态,提供制作备忘录的功能,并把这份备忘录的序号返回给用户。
final class AirConditionsSystemOriginator { private String state; ... int saveState(AirConditionsSystemCareTaker careTaker) { return careTaker.add(new SystemMemento(state)); } void restoreState(SystemMemento m) { state = m.state(); } }备忘录模式让用户能够通过备忘录机制方便地记录并恢复对象状态。这样的话,用户就不用手工创建其他一些用来记录状态的东西了(参见下图)。

图 1 用UML类图来演示几个类
备忘录模式能够帮助程序执行撤销(undo)操作,或者令其状态退回到早前的某个时间点。该模式让我们能够清晰地实现这些功能,并将不同的逻辑划分开,使得程序的代码更容易维护。