备忘录(Memento)

Intent

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

Class Diagram

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

设计模式 - 备忘录 - 图1

Implementation

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

实现参考:Memento Pattern - Calculator Example - Java Sourcecode

  1. /**
  2. * Originator Interface
  3. */
  4. public interface Calculator {
  5. // Create Memento
  6. PreviousCalculationToCareTaker backupLastCalculation();
  7. // setMemento
  8. void restorePreviousCalculation(PreviousCalculationToCareTaker memento);
  9. int getCalculationResult();
  10. void setFirstNumber(int firstNumber);
  11. void setSecondNumber(int secondNumber);
  12. }
  1. /**
  2. * Originator Implementation
  3. */
  4. public class CalculatorImp implements Calculator {
  5. private int firstNumber;
  6. private int secondNumber;
  7. @Override
  8. public PreviousCalculationToCareTaker backupLastCalculation() {
  9. // create a memento object used for restoring two numbers
  10. return new PreviousCalculationImp(firstNumber, secondNumber);
  11. }
  12. @Override
  13. public void restorePreviousCalculation(PreviousCalculationToCareTaker memento) {
  14. this.firstNumber = ((PreviousCalculationToOriginator) memento).getFirstNumber();
  15. this.secondNumber = ((PreviousCalculationToOriginator) memento).getSecondNumber();
  16. }
  17. @Override
  18. public int getCalculationResult() {
  19. // result is adding two numbers
  20. return firstNumber + secondNumber;
  21. }
  22. @Override
  23. public void setFirstNumber(int firstNumber) {
  24. this.firstNumber = firstNumber;
  25. }
  26. @Override
  27. public void setSecondNumber(int secondNumber) {
  28. this.secondNumber = secondNumber;
  29. }
  30. }
  1. /**
  2. * Memento Interface to Originator
  3. *
  4. * This interface allows the originator to restore its state
  5. */
  6. public interface PreviousCalculationToOriginator {
  7. int getFirstNumber();
  8. int getSecondNumber();
  9. }
  1. /**
  2. * Memento interface to CalculatorOperator (Caretaker)
  3. */
  4. public interface PreviousCalculationToCareTaker {
  5. // no operations permitted for the caretaker
  6. }
  1. /**
  2. * Memento Object Implementation
  3. * <p>
  4. * Note that this object implements both interfaces to Originator and CareTaker
  5. */
  6. public class PreviousCalculationImp implements PreviousCalculationToCareTaker,
  7. PreviousCalculationToOriginator {
  8. private int firstNumber;
  9. private int secondNumber;
  10. public PreviousCalculationImp(int firstNumber, int secondNumber) {
  11. this.firstNumber = firstNumber;
  12. this.secondNumber = secondNumber;
  13. }
  14. @Override
  15. public int getFirstNumber() {
  16. return firstNumber;
  17. }
  18. @Override
  19. public int getSecondNumber() {
  20. return secondNumber;
  21. }
  22. }
  1. /**
  2. * CareTaker object
  3. */
  4. public class Client {
  5. public static void main(String[] args) {
  6. // program starts
  7. Calculator calculator = new CalculatorImp();
  8. // assume user enters two numbers
  9. calculator.setFirstNumber(10);
  10. calculator.setSecondNumber(100);
  11. // find result
  12. System.out.println(calculator.getCalculationResult());
  13. // Store result of this calculation in case of error
  14. PreviousCalculationToCareTaker memento = calculator.backupLastCalculation();
  15. // user enters a number
  16. calculator.setFirstNumber(17);
  17. // user enters a wrong second number and calculates result
  18. calculator.setSecondNumber(-290);
  19. // calculate result
  20. System.out.println(calculator.getCalculationResult());
  21. // user hits CTRL + Z to undo last operation and see last result
  22. calculator.restorePreviousCalculation(memento);
  23. // result restored
  24. System.out.println(calculator.getCalculationResult());
  25. }
  26. }
  1. 110
  2. -273
  3. 110

JDK

  • java.io.Serializable