JAVA【设计模式】备忘录模式

一、定义

在这里插入图片描述

备忘录模式:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后需要的时候,能将该对象恢复到原先的状态

二、示例:

模拟场景:
1、git的提交记录,不仅能查看自己的提交记录,并且还能回滚到之前的版本

2、在⼤型互联⽹公司系统的发布上线都会记录发版的信息,包括;版本号、时间、MD5、内容信息和操作⼈。在后续上线时如果发现紧急问题,系统就会需要回滚操作,如果执⾏回滚那么也可以设置配置⽂件是否回滚。

我们接下来就使⽤备忘录模式,模拟如何记录配置⽂件信息。实际的使⽤过程中还会将信息存放到库中进⾏保存,这⾥暂时只是使⽤内存记录

备忘录模式

备忘录配置文件

package com.qf.design.behavior.memorandum;

import java.util.Date;

/**
 * 备忘录配置文件
 */
public class ConfigFile {
    private String versionNo;//版本号
    private String content;//内容
    private Date  date; //日期
    private String oprator;//操作人

    public ConfigFile(String versionNo, String content, Date date, String oprator) {
        this.versionNo = versionNo;
        this.content = content;
        this.date = date;
        this.oprator = oprator;
    }

    public String getVersionNo() {
        return versionNo;
    }

    public void setVersionNo(String versionNo) {
        this.versionNo = versionNo;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public String getOprator() {
        return oprator;
    }

    public void setOprator(String oprator) {
        this.oprator = oprator;
    }
}

备忘录类

package com.qf.design.behavior.memorandum;

/**
 * 备忘录类
 */
public class ConfigMemento {
    private ConfigFile configFile;

    public ConfigMemento(ConfigFile configFile){
        this.configFile=configFile;
    }

    public ConfigFile getConfigFile(){
        return configFile;
    }

    public void setConfigFile(ConfigFile configFile){
        this.configFile=configFile;
    }

}

备忘录操作人员:

package com.qf.design.behavior.memorandum;

public class ConfigOperator {
    private ConfigMemento configMemento;
    private ConfigFile configFile;

    public ConfigMemento getConfigMemento() {
        return configMemento;
    }

    public void setConfigMemento(ConfigMemento configMemento) {
        this.configMemento = configMemento;
    }


    public ConfigFile getConfigFile(){
        return configFile;
    }

    public void setConfigFile(ConfigFile configFile){
        this.configFile=configFile;
    }
}

管理后台

package com.qf.design.behavior.memorandum;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Admin {
    private int cursorinx=0;

    private List<ConfigMemento> configMementoList=new ArrayList<>();

    private Map<String,ConfigMemento> configMementoMap=new HashMap<>();

    public void append(ConfigMemento configMemento){
        configMementoList.add(configMemento);
        configMementoMap.put(configMemento.getConfigFile().getVersionNo(),configMemento);
        cursorinx++;
    }

    public ConfigMemento undo(){
        if (--cursorinx<=0){
            return configMementoList.get(0);
        }

        return configMementoList.get(cursorinx);
    }

    public ConfigMemento redo(){
        if (++cursorinx>=configMementoList.size()){
            return configMementoList.get(configMementoList.size()-1);
        }
        return configMementoList.get(cursorinx);
    }

    public ConfigMemento get(String version){
        ConfigMemento configMemento = configMementoMap.get(version);
        return configMemento;
    }
}

测试:ApiTest

package com.qf.design.behavior.memorandum;

import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;

public class ApiTest {

    private static Logger logger= LoggerFactory.getLogger(ApiTest.class);
    public static void main(String[] args) {
        Admin admin=new Admin();

        ConfigOperator configOperator=new ConfigOperator();
        ConfigFile configFile = new ConfigFile("1004001", "配置内容A版本", new Date(), "小王哥");
        ConfigMemento configMemento = new ConfigMemento(configFile);
        configOperator.setConfigFile(configFile);
        configOperator.setConfigMemento(configMemento);
        admin.append(configMemento);

        ConfigFile configFile1 = new ConfigFile("1004002", "配置内容B版本", new Date(), "小王哥");
        ConfigMemento configMemento1 = new ConfigMemento(configFile1);
        configOperator.setConfigFile(configFile1);
        configOperator.setConfigMemento(configMemento1);
        admin.append(configMemento1);

        ConfigFile configFile2 = new ConfigFile("10040013", "配置内容C版本", new Date(), "小王哥");
        ConfigMemento configMemento2 = new ConfigMemento(configFile2);
        configOperator.setConfigFile(configFile2);
        configOperator.setConfigMemento(configMemento2);
        admin.append(configMemento2);

        ConfigFile configFile3 = new ConfigFile("1004004", "配置内容D版本", new Date(), "小王哥");
        ConfigMemento configMemento3 = new ConfigMemento(configFile3);
        configOperator.setConfigFile(configFile3);
        configOperator.setConfigMemento(configMemento3);
        admin.append(configMemento3);

        ConfigMemento redo = admin.undo();
        ConfigFile configFile4 = redo.getConfigFile();
        logger.info("第一次版本回滚{}", JSON.toJSONString(configFile4));

        ConfigMemento redo2 = admin.undo();
        ConfigFile configFile5 = redo2.getConfigFile();
        logger.info("第二次版本回滚{}", JSON.toJSONString(configFile5));

        ConfigMemento redo3 = admin.redo();
        ConfigFile configFile6 = redo3.getConfigFile();
        logger.info("当前版本{}", JSON.toJSONString(configFile6));

        ConfigMemento configMemento4 = admin.get("1004004");
        ConfigFile configFile7 = configMemento4.getConfigFile();
        logger.info("查看版本1004004{}", JSON.toJSONString(configFile7));
    }
}

在这里插入图片描述
总结:
此种设计模式的⽅式可以满⾜在不破坏原有属性类的基础上,扩充了备忘录的功能。虽然和我们平时使⽤的思路是⼀样的,但在具体实现上还可以细细品味,这样的⽅式在⼀些源码中也有所体现。

在以上的实现中我们是将配置模拟存放到内存中,如果关机了会导致配置信息丢失,因为在⼀些真实的场景⾥还是需要存放到数据库中。那么此种存放到内存中进⾏回复的场景也不是没有,⽐Photoshop、运营⼈员操作ERP配置活动,那么也就是即时性的⼀般不需要存放到库中进⾏恢复。另外如果是使⽤内存⽅式存放备忘录,需要考虑存储问题,避免造成内存⼤量消耗。

posted @ 2022-08-30 22:40  雾托邦  阅读(71)  评论(0编辑  收藏  举报