目的

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

类图

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

备忘录类图.png

实现

以下实现了一个简单计算器程序,可以输入两个值,然后计算这两个值的和。备忘录模式允许将这两个值存储起来,然后在某个时刻用存储的状态进行恢复。
实现参考: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. }
  13. /**
  14. * Originator Implementation
  15. */
  16. public class CalculatorImp implements Calculator {
  17. private int firstNumber;
  18. private int secondNumber;
  19. @Override
  20. public PreviousCalculationToCareTaker backupLastCalculation() {
  21. // create a memento object used for restoring two numbers
  22. return new PreviousCalculationImp(firstNumber, secondNumber);
  23. }
  24. @Override
  25. public void restorePreviousCalculation(PreviousCalculationToCareTaker memento) {
  26. this.firstNumber = ((PreviousCalculationToOriginator) memento).getFirstNumber();
  27. this.secondNumber = ((PreviousCalculationToOriginator) memento).getSecondNumber();
  28. }
  29. @Override
  30. public int getCalculationResult() {
  31. // result is adding two numbers
  32. return firstNumber + secondNumber;
  33. }
  34. @Override
  35. public void setFirstNumber(int firstNumber) {
  36. this.firstNumber = firstNumber;
  37. }
  38. @Override
  39. public void setSecondNumber(int secondNumber) {
  40. this.secondNumber = secondNumber;
  41. }
  42. }
  43. /**
  44. * Memento Interface to Originator
  45. *
  46. * This interface allows the originator to restore its state
  47. */
  48. public interface PreviousCalculationToOriginator {
  49. int getFirstNumber();
  50. int getSecondNumber();
  51. }
  52. /**
  53. * Memento interface to CalculatorOperator (Caretaker)
  54. */
  55. public interface PreviousCalculationToCareTaker {
  56. // no operations permitted for the caretaker
  57. }
  58. /**
  59. * Memento Object Implementation
  60. * <p>
  61. * Note that this object implements both interfaces to Originator and CareTaker
  62. */
  63. public class PreviousCalculationImp implements PreviousCalculationToCareTaker,
  64. PreviousCalculationToOriginator {
  65. private int firstNumber;
  66. private int secondNumber;
  67. public PreviousCalculationImp(int firstNumber, int secondNumber) {
  68. this.firstNumber = firstNumber;
  69. this.secondNumber = secondNumber;
  70. }
  71. @Override
  72. public int getFirstNumber() {
  73. return firstNumber;
  74. }
  75. @Override
  76. public int getSecondNumber() {
  77. return secondNumber;
  78. }
  79. }
  80. /**
  81. * CareTaker object
  82. */
  83. public class Client {
  84. public static void main(String[] args) {
  85. // program starts
  86. Calculator calculator = new CalculatorImp();
  87. // assume user enters two numbers
  88. calculator.setFirstNumber(10);
  89. calculator.setSecondNumber(100);
  90. // find result
  91. System.out.println(calculator.getCalculationResult());
  92. // Store result of this calculation in case of error
  93. PreviousCalculationToCareTaker memento = calculator.backupLastCalculation();
  94. // user enters a number
  95. calculator.setFirstNumber(17);
  96. // user enters a wrong second number and calculates result
  97. calculator.setSecondNumber(-290);
  98. // calculate result
  99. System.out.println(calculator.getCalculationResult());
  100. // user hits CTRL + Z to undo last operation and see last result
  101. calculator.restorePreviousCalculation(memento);
  102. // result restored
  103. System.out.println(calculator.getCalculationResult());
  104. }
  105. }
  106. 运行结果
  107. 110
  108. -273
  109. 110

JDK中的体现

  • java.io.Serializable