Skip to content

备忘录设计模式备份诊断模板

备忘录设计模式(Memento pattern)用于将数据对象恢复到之前的状态

Originator 发起人

  • Originator 是持有需要被保存状态的对象。
  • 创建一个备忘录(Memento),将当前的内部状态保存起来,但不会暴露其实现细节。
  • Originator 还可以使用备忘录恢复其状态,但具体恢复哪个状态由外部决定

Memento 备忘录

  • Memento 负责存储 Originator 的内部状态
  • 通常是一个简单的数据结构,包含了 Originator 对象的特定状态信息
  • Memento 对 Originator 来说是不透明的,即 Originator 不能直接访问 Memento 的内部状态,只能通过定义好的方法来恢复状态。

Caretaker 管理者

  • Caretaker 负责保存备忘录,并且可以按需提供备忘录。
  • Caretaker 可以存储多个备忘录,以支持 Originator 状态的多个历史版本。

经典应用

  • 需要保存对象历史状态以便撤销操作的场景。
  • 需要实现对象的快照功能

案例场景:诊断内容备份

在发报告诊断内容的时候,我们希望报告人在完成报告之前再次进来可以看到上一次编写的内容,同时也支持在恢复到任意一个版本的报告内容,这种就很适合用备忘录设计模式,以下示例代码只是我在开发业务代码中简化的备忘录设计模式的雏形

定义备忘录类 Memento

  • 用途: 原始对象的状态快照
java
public class DiagnosisMemento {

    private String reportContent;

    public DiagnosisMemento(String reportContent) {
        this.reportContent = reportContent;
    }

    public DiagnosisMemento() {
    }

    public String getReportContent() {
        return reportContent;
    }

    public void setReportContent(String reportContent) {
        this.reportContent = reportContent;
    }
}

定义 Originator 发起人

java
public class DiagnosisOrinator {

    private String diagnosisContext;


    public String getDiagnosisContext() {
        return diagnosisContext;
    }


    public void setDiagnosisContext(String diagnosisContext) {
        this.diagnosisContext = diagnosisContext;
    }

    public DiagnosisMemento createMemento() {
        return new DiagnosisMemento(diagnosisContext);
    }

    public void restoreMemento(DiagnosisMemento memento) {
        this.diagnosisContext = memento.getReportContent();
    }
}

定义 Caretaker 管理者

java
public class DiagnosisCaretaker {

    private final RedisTemplate redisTemplate;


    public DiagnosisCaretaker(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    public void saveMemento(String key,DiagnosisMemento memento) {
        redisTemplate.opsForList().rightPush(key,memento.getReportContent());
    }

    public DiagnosisMemento retrieveMemento(String key,long index) {
        String diagnosisContext = (String)redisTemplate.opsForList().index(key, index);
        return new DiagnosisMemento(diagnosisContext);
    }

    public Long getDiagnosisListSize(String key) {
        return redisTemplate.opsForList().size(key);
    }

    public void clear(String key) {
        redisTemplate.delete(key);
    }
}

测试类

java
 @Test
    public void testMemento() {
        DiagnosisCaretaker diagnosisCaretaker = new DiagnosisCaretaker(redisTemplate);
        String key = "CASEID:001";
        diagnosisCaretaker.saveMemento(key,new DiagnosisMemento("报告备份1"));
        diagnosisCaretaker.saveMemento(key,new DiagnosisMemento("报告备份2"));
        diagnosisCaretaker.saveMemento(key,new DiagnosisMemento("报告备份3"));
        diagnosisCaretaker.saveMemento(key,new DiagnosisMemento("报告备份4"));
        diagnosisCaretaker.saveMemento(key,new DiagnosisMemento("报告备份5"));

        log.info("报告备份总数量" + diagnosisCaretaker.getDiagnosisListSize(key));

        DiagnosisMemento memento = diagnosisCaretaker.retrieveMemento(key, 0);
        String reportContent = memento.getReportContent();
        log.info("获取 :{}",reportContent);

        DiagnosisMemento memento1 = diagnosisCaretaker.retrieveMemento(key, 1);
        String reportContent1 = memento1.getReportContent();
        log.info("获取 :{}",reportContent1);

        DiagnosisMemento memento2 = diagnosisCaretaker.retrieveMemento(key, 2);
        String reportContent2 = memento2.getReportContent();
        log.info("获取 :{}",reportContent2);

        log.info("清除报告");
        diagnosisCaretaker.clear(key);

        log.info("报告备份总数量" + diagnosisCaretaker.getDiagnosisListSize(key));
    }

输出如下:

text
2024-08-27 18:00:38.073  INFO 9624 --- [           main] c.s.d.DesignPatternsApplicationTest      : 报告备份总数量5
2024-08-27 18:00:38.079  INFO 9624 --- [           main] c.s.d.DesignPatternsApplicationTest      : 获取 :报告备份1
2024-08-27 18:00:38.080  INFO 9624 --- [           main] c.s.d.DesignPatternsApplicationTest      : 获取 :报告备份2
2024-08-27 18:00:38.080  INFO 9624 --- [           main] c.s.d.DesignPatternsApplicationTest      : 获取 :报告备份3
2024-08-27 18:00:38.080  INFO 9624 --- [           main] c.s.d.DesignPatternsApplicationTest      : 清除报告
2024-08-27 18:00:38.082  INFO 9624 --- [           main] c.s.d.DesignPatternsApplicationTest      : 报告备份总数量0

Released under the MIT License.