备忘录模式是一种软件设计模式:在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
这种设计模式无论在生活中还是开发中都是非常常见的,比如不存在的后悔药等,而在开发中比如ctrl+z回退、Photoshop的历史记录等
而对于我们开发者比较常见的一个功能在于发布程序版本的,有时候紧急部署一个新的版本却发现不能用,我们可以迅速的回滚到上个版本。在示例程序中我们模拟在发布上线的过程中记录线上配置文件用于紧急回滚
名称 | 说明 |
---|---|
ConfigFile | 配置文件类,此类不属于备忘录模式的核心 |
ConfigMemento | 备忘录类,此类管理ConfigFile |
ConfigOriginator | 记录者类,此类拥有生成ConfigMemento的方法 |
Admin | 管理员类 |
ConfigFile
@Data
@AllArgsConstructor
public class ConfigFile {
private String versionNo; // 版本号
private String content; // 内容
private Date dateTime; // 时间
private String operator; // 操作人
}
ConfigMemento
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ConfigMemento {
private ConfigFile configFile;
}
ConfigOriginator
saveMemento保存包网路的时候会创建一个备忘录信息,并返回去,交给管理者处理
getMemento获取到之后并不是直接返回,而是把备忘录的信息交给现在的配置文件this.configFile
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ConfigOriginator {
private ConfigFile configFile;
public ConfigMemento saveMemento(){
return new ConfigMemento(configFile);
}
public void getMemento(ConfigMemento memento){
this.configFile = memento.getConfigFile();
}
}
Admin
public class Admin {
private int cursorIdx = 0;
private List<ConfigMemento> mementoList = new ArrayList<>();
private Map<String, ConfigMemento> mementoMap = new ConcurrentHashMap<>();
public void append(ConfigMemento memento){
cursorIdx++;
mementoList.add(memento);
mementoMap.put(memento.getConfigFile().getVersionNo(),memento);
}
//回退一个版本
public ConfigMemento undo(){
if (--cursorIdx <= 0) {
return mementoList.get(0);
}
return mementoList.get(cursorIdx);
}
//前进一个版本
public ConfigMemento redo(){
if (++cursorIdx > mementoMap.size()){
return mementoList.get(mementoMap.size() - 1);
}
return mementoList.get(cursorIdx);
}
//获取某一个版本
public ConfigMemento get(String versionNo){
return mementoMap.get(versionNo);
}
}
Test
@SpringBootTest
class Practice2000ApplicationTests {
@Test
void contextLoads() {
Admin admin = new Admin();
ConfigOriginator configOriginator = new ConfigOriginator();
configOriginator.setConfigFile(new ConfigFile("yellowstar0.0.1", "第一次", new Date(), "yellowstar"));
admin.append(configOriginator.saveMemento());
configOriginator.setConfigFile(new ConfigFile("yellowstar0.0.2", "第二次", new Date(), "yellowstar"));
admin.append(configOriginator.saveMemento());
configOriginator.setConfigFile(new ConfigFile("yellowstar0.0.3", "第三次", new Date(), "yellowstar"));
admin.append(configOriginator.saveMemento());
configOriginator.setConfigFile(new ConfigFile("yellowstar0.0.4", "第四次", new Date(), "yellowstar"));
admin.append(configOriginator.saveMemento());
configOriginator.getMemento(admin.undo());
System.out.println("回滚一次" + configOriginator.getConfigFile());
configOriginator.getMemento(admin.undo());
System.out.println("再回滚一次" + configOriginator.getConfigFile());
configOriginator.getMemento(admin.redo());
System.out.println("前进一次" + configOriginator.getConfigFile());
configOriginator.getMemento(admin.get("yellowstar0.0.1"));
System.out.println("到达指定版本" + configOriginator.getConfigFile());
}
}
//结果
回滚一次ConfigFile(versionNo=yellowstar0.0.4, content=第四次, dateTime=Wed Jun 22 14:48:51 CST 2022, operator=yellowstar)
再回滚一次ConfigFile(versionNo=yellowstar0.0.3, content=第三次, dateTime=Wed Jun 22 14:48:51 CST 2022, operator=yellowstar)
前进一次ConfigFile(versionNo=yellowstar0.0.4, content=第四次, dateTime=Wed Jun 22 14:48:51 CST 2022, operator=yellowstar)
到达指定版本ConfigFile(versionNo=yellowstar0.0.1, content=第一次, dateTime=Wed Jun 22 14:48:51 CST 2022, operator=yellowstar)
备忘录模式是一种对象行为型模式,其主要优点如下
缺点也很明显