1. 意图(Intent)

在不违反封装的情况下获得对象的内部状态,从而在需要时可以将对象恢复到最初状态。

2. 类图(Class Diagram)

50678f34-694f-45a4-91c6-34d985c83fee.png

  • Originator:原始对象
  • Caretaker :负责保存好备忘录
  • Memento :备忘录,存储原始对象的状态。备忘录实际上有两个接口
    1. 1. 一个是提供给 Caretaker 的窄接口,它只能将备忘录传递给其它对象;
    2. 1. 一个是提供给 Originator 的宽接口,允许它访问到先前状态所需的所有数据。理想情况是只允许 Originator 访问本备忘录的内部状态。

    3. 实现(Implementation)

以下实现了一个简单计算器程序,可以输入两个值,然后计算这两个值的和。备忘录模式允许将这两个值存储起来,然后在某个时刻用存储的状态进行恢复。
image.png

操作方法接口 (定义了对原始对象的操作方法)

public interface Calculator {

    // 创建备忘录
    PreviousCalculationToCareTaker backupLastCalculation();

    // 创建备忘录
    void restorePreviousCalculation(PreviousCalculationToCareTaker memento);

    int getCalculationResult();

    void setFirstNumber(int firstNumber);

    void setSecondNumber(int secondNumber);
}

实现了接口方法的计算实现类 (实现了具体的方法,如何对原始对象 Originator 进行操作)

public class CalculatorImp implements Calculator {

    private int firstNumber;
    private int secondNumber;

    @Override
    public PreviousCalculationToCareTaker backupLastCalculation() {
        // 创建一个用于恢复两个数字的备忘录对象
        return new PreviousCalculationImp(firstNumber, secondNumber);
    }

    @Override
    public void restorePreviousCalculation(PreviousCalculationToCareTaker memento) {
        this.firstNumber = ((PreviousCalculationToOriginator) memento).getFirstNumber();
        this.secondNumber = ((PreviousCalculationToOriginator) memento).getSecondNumber();
    }

    @Override
    public int getCalculationResult() {
        // result is adding two numbers
        return firstNumber + secondNumber;
    }

    @Override
    public void setFirstNumber(int firstNumber) {
        this.firstNumber = firstNumber;
    }

    @Override
    public void setSecondNumber(int secondNumber) {
        this.secondNumber = secondNumber;
    }
}

针对原始对象进行备忘方法接口 [ Originator ]

// 该接口允许发起者恢复其状态
public interface PreviousCalculationToOriginator {
    int getFirstNumber();
    int getSecondNumber();
}

负责保存备忘录的接口 [ Caretaker ]

// 负责保存好备忘录
public interface PreviousCalculationToCareTaker {
    // no operations permitted for the caretaker (caretaker不允许进行任何操作)
}

备忘录实现类 [ Memento ]

// 请注意,此对象同时实现了 Originator 和 CareTaker 的接口
public class PreviousCalculationImp implements PreviousCalculationToCareTaker,
        PreviousCalculationToOriginator {

    private int firstNumber;
    private int secondNumber;

    public PreviousCalculationImp(int firstNumber, int secondNumber) {
        this.firstNumber = firstNumber;
        this.secondNumber = secondNumber;
    }

    @Override
    public int getFirstNumber() {
        return firstNumber;
    }

    @Override
    public int getSecondNumber() {
        return secondNumber;
    }
}

客户端演示代码:

public class Client {

    public static void main(String[] args) {

        Calculator calculator = new CalculatorImp();

        // 假设用户设置两个数字
        calculator.setFirstNumber(10);
        calculator.setSecondNumber(100);

        // 计算结果
        System.out.println(calculator.getCalculationResult());

        // 存储此计算的结果以防出错
        PreviousCalculationToCareTaker memento = calculator.backupLastCalculation();

        // 用户设置一个数字
        calculator.setFirstNumber(17);

        // 用户设置错误的第二个数字并计算结果
        calculator.setSecondNumber(-290);

        // 计算结果
        System.out.println(calculator.getCalculationResult());

        // 用户按 CTRL + Z 撤消上次操作并查看上次结果
        calculator.restorePreviousCalculation(memento);

        // 恢复之前结果
        System.out.println(calculator.getCalculationResult());
    }
}

输出:

110
-273
110


4. JDK

  • java.io.Serializable