Learn Java design mode again: actual memo mode "simulate the scenario of profile rollback during the online process of Internet system"

Keywords: Java JSON JDK Maven

Author: little brother Fu
Blog: https://bugstack.cn -Original series of special articles

Precipitation, sharing, growth, so that they and others can have a harvest! 😄

1, Preface

Can't it be an excuse for R & D?

Sometimes the function complexity is high and it is difficult to realize, sometimes the construction period is short and the implementation is not complete. The behavior of coding is a process that is not easy to quantify. For the same function, everyone has different ways to implement it, and the speed of solving problems is also different when encountering development problems. In addition, it is very difficult to explain to the product why this construction period is needed. It is just like how much cement mortar is needed in the final drawing of a building. At this time, R & D will try its best to establish process specifications, design, development, review, etc., to determine a time range that can be completed and avoid risks. If it is compressed again, there will be some contradictions. If it can be compressed, it is necessary to explain why it took so much time before it can not be compressed, and there is constant pressure from all parties. Therefore, sometimes it is not necessarily an excuse, but to consider how to make the whole team develop healthily.

Encouragement is sometimes more important than stress!

In the process of learning, many times what we hear is, what you want, how, who and who, even if we can't hear such voice today, but because we have heard it repeatedly, it leads to inner resistance. Although I know I want to learn, it's hard to stick to it. If I learn, I have no direction. When I see so many things that I can't, I'm more flustered, and I'm not willing to learn. In fact, the pressure of programmers is not small, and they almost need to learn to grow up. Just like they can't say they are proficient in java any more, the amount of knowledge is actually deeper and wider with the deepening of learning. So need, happy study, happy growth!

You seem to be in a hurry!

I often hear that. The teacher will ask you to help me to do it tomorrow. Write something for me. I will learn this time. Now I have no time to learn. Please show me. In fact, there are many similar ones. I wonder how your anxiety came about. It's impossible for people to sit at home and misfortune falls from the sky. How can the teacher find you at that time? How can the boss take care of you today? It's not that you haven't studied for a long time. You're in a hurry! Even if someone really helps you later, it's better not to relax, learn as soon as possible, and avoid the first and second day of junior high!

2, Development environment

  1. JDK 1.8
  2. Idea + Maven
  3. One project involves official account number: bugstack wormhole stack , reply to the source code download and obtain (open the obtained link and find the No. 18)
engineering describe
itstack-demo-design-17-00 Development profile memo

3, Introduction to memo mode

Memo mode is a design pattern which can restore or roll back, configure, version and repent. This design pattern belongs to behavior pattern. In terms of function implementation, the memo operation class is added on the basis of not destroying the original object to record the behavior of the original object so as to realize the memo mode.

This design is also more common in our daily life or development, such as regret medicine, Meng Po Tang (roll back to 0), IDEA editing and revocation, little overlord game machine archive. Of course, there are also our very common Photoshop, as follows;

4, Case scenario simulation

In this case, we simulate that the system records the online configuration file for emergency rollback during the release and launch process

It must be easy to use, safe and emergency handling when the system is released and launched in a large Internet company. At the same time, in order to isolate the online and local environment, the configuration files are generally extracted and put on the line, so as to avoid the local configuration content being released due to misoperation. At the same time, online configuration files will also be recorded at each change, including version number, time, MD5, content information and operator.

If emergency problems are found during subsequent online operation, the system will need to roll back. If rollback is performed, you can also set whether the configuration file is rolled back. Because each version of the system may carry some configuration file information with it, it is very convenient for the system and configuration file to roll back together at this time.

Let's use the memo mode to simulate how to record the profile information. In the actual use process, the information will also be stored in the library for saving. Here, only memory records are used temporarily.

5, Memo mode records profile version information

The key point of implementing the design pattern of memo is to add the storage record of memo class without changing the original class. Although it may not be necessary to implement their own requirements according to the code structure of this design pattern in normal times, similar functions may have been completed to record the system information.

In addition to the current case, it can also be the record of information created by the operators in the background erp, so that the operators can modify their version up and down, without losing information due to misoperation.

1. Engineering structure

└── src
    ├── main
    │   └── java
    │       └── org.itstack.demo.design
    │           ├── Admin.java
    │           ├── ConfigFile.java
    │           ├── ConfigMemento.java
    │           └── ConfigOriginator.java
    └── test
        └── java
            └── org.itstack.demo.design.test
                └── ApiTest.java

Memo model structure

  • The above is a class diagram of the engineering structure. In fact, it is relatively uncomplicated. In addition to the original configuration class (ConfigFile), only three new classes are added.
  • ConfigMemento: memo class, which is the extension of the original configuration class
  • Configinator: logger class, which gets and returns memo class object information
  • Admin: administrator class, used to record the memo information, such as the sequence of some columns or the content information of a certain version

2. Code implementation

2.1 configuration information class

public class ConfigFile {

    private String versionNo; // Version number
    private String content;   // content
    private Date dateTime;    // time
    private String operator;  // Operator
    // ...get/set
  • Configuration class can be in any form. Here is a simple description of basic configuration content information.

2.2 memoranda

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;
  • Memo is an extension of the original configuration class, which can set and obtain configuration information.

2.3 recorder

public class ConfigOriginator {

    private ConfigFile configFile;

    public ConfigFile getConfigFile() {
        return configFile;

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

    public ConfigMemento saveMemento(){
        return new ConfigMemento(configFile);

    public void getMemento(ConfigMemento memento){
        this.configFile = memento.getConfigFile();

  • In addition to the acquisition and setting methods added to the ConfigFile configuration class, the recorder class also adds save memento(), get getmemento (configmemoento memento).
  • Save memo: when saving a memo, a memo information will be created and returned to the administrator for processing.
  • getMemento: after obtaining the memo, it is not returned directly, but the memo information is handed to the current configuration file this.configFile , this part needs attention.

2.4 administrator class

public class Admin {

    private int cursorIdx = 0;
    private List<ConfigMemento> mementoList = new ArrayList<ConfigMemento>();
    private Map<String, ConfigMemento> mementoMap = new ConcurrentHashMap<String, ConfigMemento>();

    public void append(ConfigMemento 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 > mementoList.size()) return mementoList.get(mementoList.size() - 1);
        return mementoList.get(cursorIdx);

    public ConfigMemento get(String versionNo){
        return mementoMap.get(versionNo);

  • The core function of this class is to record the configuration file information, that is, the effect of the memo, and then provide methods to roll back and get the memo content.
  • At the same time, two data structures are set here to store the memo, which can be set on demand in actual use. List<ConfigMemento>,Map<String, ConfigMemento>.
  • Finally, the memo operation methods are provided: append, undo, redo and get.

3. Test and verification

3.1 write test class

public void test() {
    Admin admin = new Admin();
    ConfigOriginator configOriginator = new ConfigOriginator();
    configOriginator.setConfigFile(new ConfigFile("1000001", "Configuration content A=ha-ha", new Date(), "Little brother Fu"));
    admin.append(configOriginator.saveMemento()); // Save configuration
    configOriginator.setConfigFile(new ConfigFile("1000002", "Configuration content A=Hee hee", new Date(), "Little brother Fu"));
    admin.append(configOriginator.saveMemento()); // Save configuration
    configOriginator.setConfigFile(new ConfigFile("1000003", "Configuration content A=kiss", new Date(), "Little brother Fu"));
    admin.append(configOriginator.saveMemento()); // Save configuration
    configOriginator.setConfigFile(new ConfigFile("1000004", "Configuration content A=hey", new Date(), "Little brother Fu"));
    admin.append(configOriginator.saveMemento()); // Save configuration  

    // Historical configuration (rollback)
    logger.info("Historical configuration(RollBACK )undo: {}", JSON.toJSONString(configOriginator.getConfigFile()));  

    // Historical configuration (rollback)
    logger.info("Historical configuration(RollBACK )undo: {}", JSON.toJSONString(configOriginator.getConfigFile()));  

    // Historical configuration (forward)
    logger.info("Historical configuration(forward)redo: {}", JSON.toJSONString(configOriginator.getConfigFile()));   

    // Historical configuration (get)
    logger.info("Historical configuration(obtain)get: {}", JSON.toJSONString(configOriginator.getConfigFile()));
  • Part of the learning of this design pattern focuses on the unit test class, which includes four information storage and memo history configuration operations.
  • After the above four configurations are added, the following operations are as follows: roll back 1 time, roll back 1 time, and then move forward 1 time. Finally, get the specified version configuration. The specific effect can refer to the test results.

3.2 test results

23:12:09.512 [main] INFO  org.itstack.demo.design.test.ApiTest - Historical configuration(RollBACK )undo: {"content":"Configuration content A=hey","dateTime":159209829432,"operator":"Little brother Fu","versionNo":"1000004"}
23:12:09.514 [main] INFO  org.itstack.demo.design.test.ApiTest - Historical configuration(RollBACK )undo: {"content":"Configuration content A=kiss","dateTime":159209829432,"operator":"Little brother Fu","versionNo":"1000003"}
23:12:09.514 [main] INFO  org.itstack.demo.design.test.ApiTest - Historical configuration(forward)redo: {"content":"Configuration content A=hey","dateTime":159209829432,"operator":"Little brother Fu","versionNo":"1000004"}
23:12:09.514 [main] INFO  org.itstack.demo.design.test.ApiTest - Historical configuration(obtain)get: {"content":"Configuration content A=Hee hee","dateTime":159320989432,"operator":"Little brother Fu","versionNo":"1000002"}

Process finished with exit code 0
  • From the test results, we can see that the historical configuration is rolled back and advanced according to our instructions, and finally obtained through the specified version, which meets the expected results.

6, Summary

  • This design pattern can extend the function of memo without destroying the original attribute class. Although we usually use the same idea, but in the specific implementation can also be savored, such a way in some source code is also reflected.
  • In the above implementation, we store the configuration simulation in memory. If it is shut down, the configuration information will be lost, because in some real scenarios, it still needs to be stored in the database. This kind of storage in memory for recovery scenarios is not without, for example, Photoshop, operators operate ERP configuration activities, that is, instant, generally do not need to be stored in the library for recovery. In addition, the memory storage method should be considered to avoid memory consumption.
  • Design pattern learning is to better write scalable, manageable, easy to maintain code, and this learning process needs to constantly try practical operation, the combination of theoretical knowledge and practice is still a long way to go. Remember to do more!

7, Recommended reading

Posted by emmbec on Sun, 28 Jun 2020 21:45:05 -0700