备忘录模式(Memento Pattern)

162 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第7天,点击查看活动详情

1 简介

意图:在不破坏封装性前提下,捕获一个对象的内部状态,并在该对象之外保存该状态。就能在以后将对象恢复到原先保存的状态。

何时使用:很多时候我们总需记录一个对象的内部状态,为了允许用户取消不确定或错误的操作,能够恢复到他原先的状态,即"后悔药"。

如何解决:通过一个备忘录类专门存储对象状态。

关键代码:客户不与备忘录类耦合,与备忘录管理类耦合。

应用实例:

  • 游戏存档
  • ctrl + z
  • 浏览器中的后退
  • 数据库事务管理

2 优点

给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。

实现了信息的封装,使得用户不需要关心状态的保存细节。

3 缺点

消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。

4 使用场景

1、需要保存/恢复数据的相关状态场景。

2、提供一个可回滚的操作

为符合迪米特原则,还要增加一个管理备忘录的类。 为了节约内存,可使用原型模式+备忘录模式。

5 实现-MementoPatternDemo

备忘录模式使用三个类 MementoOriginatorCareTaker。Memento 包含了要被恢复的对象的状态。Originator 创建并在 Memento 对象中存储状态。Caretaker 对象负责从 Memento 中恢复对象的状态。

使用 CareTakerOriginator 对象来显示对象的状态恢复。

备忘录模式的 UML 图

创建 Memento 类:

 package com.javaedge.design.pattern.behavioral.memento.v2;
 ​
 import lombok.AllArgsConstructor;
 import lombok.Getter;
 ​
 /**
  * @author JavaEdge
  * @date 2022/10/4
  */
 @AllArgsConstructor
 @Getter
 public class Memento {
 ​
     private String state;
 }
 ​

创建 Originator 类。

 package com.javaedge.design.pattern.behavioral.memento.v2;
 ​
 import lombok.Data;
 ​
 /**
  * @author apple
  * @date 2022/10/4
  */
 @Data
 public class Originator {
     
     private String state;
 ​
     public Memento saveStateToMemento() {
         return new Memento(state);
     }
 ​
     public void getStateFromMemento(Memento Memento) {
         state = Memento.getState();
     }
 }
 ​

创建 CareTaker 类。

 package com.javaedge.design.pattern.behavioral.memento.v2;
 ​
 import java.util.ArrayList;
 import java.util.List;
 ​
 /**
  * @author JavaEdge
  * @date 2022/10/4
  */
 public class CareTaker {
 ​
     private List<Memento> mementoList = new ArrayList<>();
 ​
     public void add(Memento state) {
         mementoList.add(state);
     }
 ​
     public Memento get(int index) {
         return mementoList.get(index);
     }
 }
 ​

使用 CareTakerOriginator 对象。MementoPatternDemo

 package com.javaedge.design.pattern.behavioral.memento.v2;
 ​
 /**
  * @author JavaEdge
  * @date 2022/10/4
  */
 public class MementoPatternDemo {
     public static void main(String[] args) {
         Originator originator = new Originator();
         CareTaker careTaker = new CareTaker();
         originator.setState("State #1");
         originator.setState("State #2");
         careTaker.add(originator.saveStateToMemento());
         originator.setState("State #3");
         careTaker.add(originator.saveStateToMemento());
         originator.setState("State #4");
 ​
         System.out.println("Current State: " + originator.getState());
         originator.getStateFromMemento(careTaker.get(0));
         System.out.println("First saved State: " + originator.getState());
         originator.getStateFromMemento(careTaker.get(1));
         System.out.println("Second saved State: " + originator.getState());
     }
 }
 ​

验证输出。

 Current State: State #4
 First saved State: State #2
 Second saved State: State #3

\