Design Mode-Memo Mode

1 Introduction

Everyone makes mistakes and hopes that there is a kind of "regret medicine" that can make up for their mistakes and allow themselves to start again, but the reality is cruel. In computer applications, customers also often make mistakes. Can you provide them with "regret medicine"? Of course it is possible and necessary. This function is realized by the "memorandum mode".

In fact, many application software provide this function, such as Word, Notepad, Photoshop, Eclipse and other software, when you press the Ctrl+Z key combination during editing, you can undo the current operation and restore the document to the previous state; and in IE The back button of the database, the rollback operation in database transaction management, the archive function of intermediate results when playing games, the backup operation of the database and operating system, the regret function in chess games, etc. belong to this category.

The memo mode can record the internal state of an object, and when the user regrets it, it can undo the current operation and restore the data to its original state.

2. The definition and characteristics of the model

The definition of the Memento mode: Under the premise of not destroying the encapsulation, capture the internal state of an object, and save this state outside the object, so that the object can be restored to the original state when needed. This mode is also called snapshot mode.

The memo mode is an object behavioral mode, and its main advantages are as follows:

  • Provides a mechanism to restore the state. When the user needs it, it can easily restore the data to a certain historical state.
  • The encapsulation of the internal state is realized. Except for the initiator who created it, no other objects can access this state information.
  • Simplified initiating human beings. The initiator does not need to manage and save individual backups of its internal state. All state information is stored in the memo and managed by the manager, which conforms to the single responsibility principle.

The main disadvantage is: high resource consumption. If the internal state information to be saved is too much or very frequently, it will take up relatively large memory resources.

3. The structure and realization of the pattern

The core of the memo pattern is to design the memo class and the manager class used to manage the memo. Now let's learn its structure and implementation.

1. The structure of the model

The main roles of the memo mode are as follows:

  1. Originator role: It records the current internal state information, provides the functions of creating memos and restoring memo data, and realizes other business functions. It can access all the information in the memo.
  2. Memento role: Responsible for storing the internal state of the initiator and providing these internal states to the initiator when needed.
  3. Manager (Caretaker) role: Manage memos, provide the functions of saving and obtaining memos, but they cannot access and modify the content of memos.

Insert picture description here

2. Implementation of the pattern

package net.biancheng.c.memento;

public class MementoPattern {
    
    
    public static void main(String[] args) {
    
    
        Originator or = new Originator();
        Caretaker cr = new Caretaker();
        or.setState("S0");
        System.out.println("初始状态:" + or.getState());
        cr.setMemento(or.createMemento()); //保存状态
        or.setState("S1");
        System.out.println("新的状态:" + or.getState());
        or.restoreMemento(cr.getMemento()); //恢复状态
        System.out.println("恢复状态:" + or.getState());
    }
}

//备忘录
class Memento {
    
    
    private String state;

    public Memento(String state) {
    
    
        this.state = state;
    }

    public void setState(String state) {
    
    
        this.state = state;
    }

    public String getState() {
    
    
        return state;
    }
}

//发起人
class Originator {
    
    
    private String state;

    public void setState(String state) {
    
    
        this.state = state;
    }

    public String getState() {
    
    
        return state;
    }

    public Memento createMemento() {
    
    
        return new Memento(state);
    }

    public void restoreMemento(Memento m) {
    
    
        this.setState(m.getState());
    }
}

//管理者
class Caretaker {
    
    
    private Memento memento;

    public void setMemento(Memento m) {
    
    
        memento = m;
    }

    public Memento getMemento() {
    
    
        return memento;
    }
}

Initial state: S0
New state: S1
Recovery state: S0

4. Application examples of the pattern

[Example 1] Use the memo mode to design a blind date game.

Analysis: If you have a blind date with Xi Shi, Wang Zhaojun, Diao Chan, and Yang Yuhuan, you can choose one of them as your lover; of course, if you are not satisfied with the previous choice, you can choose again, but hope you Don't be too distracted; this game provides regret function, it is more appropriate to use the "memo mode" design.

First, design a girl category, which is a memo role, which provides the function of obtaining and storing beauty information; then, design a blind date (You) category, which is the initiator role, which records the internal state of the current moment Information (the name of the temporary wife), and provide the function of creating memos and restoring memo data; finally, define a GirlStack class, which is the manager role, responsible for managing the memo, and used to save the blind date (You) The beauty information selected before, but only 4 can be saved at most, and the regret function is provided.

The client class is designed as a window program, which contains the GirlStack object and the blind date (You) object. It implements the event processing method actionPerformed (ActionEvent e) of the ActionListener interface, and combines the 4 beautiful images and the blind date (You) ) The selected beauty image is displayed in the window. Figure 2 shows its structure.

Insert picture description here

package net.biancheng.c.memento;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class DatingGame {
    
    
    public static void main(String[] args) {
    
    
        new DatingGameWin();
    }
}

//客户窗体类
class DatingGameWin extends JFrame implements ActionListener {
    
    
    private static final long serialVersionUID = 1L;
    JPanel CenterJP, EastJP;
    JRadioButton girl1, girl2, girl3, girl4;
    JButton button1, button2;
    String FileName;
    JLabel g;
    You you;
    GirlStack girls;

    DatingGameWin() {
    
    
        super("利用备忘录模式设计相亲游戏");
        you = new You();
        girls = new GirlStack();
        this.setBounds(0, 0, 900, 380);
        this.setResizable(false);
        FileName = "src/memento/Photo/四大美女.jpg";
        g = new JLabel(new ImageIcon(FileName), JLabel.CENTER);
        CenterJP = new JPanel();
        CenterJP.setLayout(new GridLayout(1, 4));
        CenterJP.setBorder(BorderFactory.createTitledBorder("四大美女如下:"));
        CenterJP.add(g);
        this.add("Center", CenterJP);
        EastJP = new JPanel();
        EastJP.setLayout(new GridLayout(1, 1));
        EastJP.setBorder(BorderFactory.createTitledBorder("您选择的爱人是:"));
        this.add("East", EastJP);
        JPanel SouthJP = new JPanel();
        JLabel info = new JLabel("四大美女有“沉鱼落雁之容、闭月羞花之貌”,您选择谁?");
        girl1 = new JRadioButton("西施", true);
        girl2 = new JRadioButton("貂蝉");
        girl3 = new JRadioButton("王昭君");
        girl4 = new JRadioButton("杨玉环");
        button1 = new JButton("确定");
        button2 = new JButton("返回");
        ButtonGroup group = new ButtonGroup();
        group.add(girl1);
        group.add(girl2);
        group.add(girl3);
        group.add(girl4);
        SouthJP.add(info);
        SouthJP.add(girl1);
        SouthJP.add(girl2);
        SouthJP.add(girl3);
        SouthJP.add(girl4);
        SouthJP.add(button1);
        SouthJP.add(button2);
        button1.addActionListener(this);
        button2.addActionListener(this);
        this.add("South", SouthJP);
        showPicture("空白");
        you.setWife("空白");
        girls.push(you.createMemento());    //保存状态
    }

    //显示图片
    void showPicture(String name) {
    
    
        EastJP.removeAll(); //清除面板内容
        EastJP.repaint(); //刷新屏幕
        you.setWife(name);
        FileName = "src/memento/Photo/" + name + ".jpg";
        g = new JLabel(new ImageIcon(FileName), JLabel.CENTER);
        EastJP.add(g);
        this.setVisible(true);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
    
    
        boolean ok = false;
        if (e.getSource() == button1) {
    
    
            ok = girls.push(you.createMemento());    //保存状态
            if (ok && girl1.isSelected()) {
    
    
                showPicture("西施");
            } else if (ok && girl2.isSelected()) {
    
    
                showPicture("貂蝉");
            } else if (ok && girl3.isSelected()) {
    
    
                showPicture("王昭君");
            } else if (ok && girl4.isSelected()) {
    
    
                showPicture("杨玉环");
            }
        } else if (e.getSource() == button2) {
    
    
            you.restoreMemento(girls.pop()); //恢复状态
            showPicture(you.getWife());
        }
    }
}

//备忘录:美女
class Girl {
    
    
    private String name;

    public Girl(String name) {
    
    
        this.name = name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    public String getName() {
    
    
        return name;
    }
}

//发起人:您
class You {
    
    
    private String wifeName;    //妻子

    public void setWife(String name) {
    
    
        wifeName = name;
    }

    public String getWife() {
    
    
        return wifeName;
    }

    public Girl createMemento() {
    
    
        return new Girl(wifeName);
    }

    public void restoreMemento(Girl p) {
    
    
        setWife(p.getName());
    }
}

//管理者:美女栈
class GirlStack {
    
    
    private Girl girl[];
    private int top;

    GirlStack() {
    
    
        girl = new Girl[5];
        top = -1;
    }

    public boolean push(Girl p) {
    
    
        if (top >= 4) {
    
    
            System.out.println("你太花心了,变来变去的!");
            return false;
        } else {
    
    
            girl[++top] = p;
            return true;
        }
    }

    public Girl pop() {
    
    
        if (top <= 0) {
    
    
            System.out.println("美女栈空了!");
            return girl[0];
        } else return girl[top--];
    }
}

5. Application scenarios of the mode

I learned the definition, characteristics, structure, and implementation of the memo mode. Now let’s look at the following application scenarios of this mode.

  1. Scenes that need to save and restore data, such as the archive function of intermediate results when playing games.
  2. Need to provide a scene that can be rolled back, such as Word, Notepad, Photoshop, Eclipse and other software, press Ctrl+Z key combination when editing, and transaction operations in the database.

6. Expansion of the pattern

In the memo mode introduced earlier, there are examples of single-state backup and multi-state backup. The following describes how the memo mode is mixed with the prototype mode. In the memo mode, the "initiator" information is backed up by defining the "memorandum", and the clone() method of the prototype mode has a self-backup function. Therefore, if the initiator is allowed to implement the Cloneable interface, it will have the function of backing up itself. You can delete the memo category, and its structure is shown in Figure 4.

Insert picture description here

package net.biancheng.c.memento;

public class PrototypeMemento {
    
    
    public static void main(String[] args) {
    
    
        OriginatorPrototype or = new OriginatorPrototype();
        PrototypeCaretaker cr = new PrototypeCaretaker();
        or.setState("S0");
        System.out.println("初始状态:" + or.getState());
        cr.setMemento(or.createMemento()); //保存状态
        or.setState("S1");
        System.out.println("新的状态:" + or.getState());
        or.restoreMemento(cr.getMemento()); //恢复状态
        System.out.println("恢复状态:" + or.getState());
    }
}

//发起人原型
class OriginatorPrototype implements Cloneable {
    
    
    private String state;

    public void setState(String state) {
    
    
        this.state = state;
    }

    public String getState() {
    
    
        return state;
    }

    public OriginatorPrototype createMemento() {
    
    
        return this.clone();
    }

    public void restoreMemento(OriginatorPrototype opt) {
    
    
        this.setState(opt.getState());
    }

    public OriginatorPrototype clone() {
    
    
        try {
    
    
            return (OriginatorPrototype) super.clone();
        } catch (CloneNotSupportedException e) {
    
    
            e.printStackTrace();
        }
        return null;
    }
}

//原型管理者
class PrototypeCaretaker {
    
    
    private OriginatorPrototype opt;

    public void setMemento(OriginatorPrototype opt) {
    
    
        this.opt = opt;
    }

    public OriginatorPrototype getMemento() {
    
    
        return opt;
    }
}

Initial state: S0
New state: S1
Recovery state: S0

Guess you like

Origin blog.csdn.net/saienenen/article/details/112706473