Everyone makes mistakes and hopes to have a "regret medicine" to make up for their mistakes and start over, but the reality is cruel. In computer applications, customers also often make mistakes. Can we provide them with "regret medicine"? Of course, it is possible and necessary. This function is realized by "memo mode".
In fact, many application software provide this function, such as Word, Notepad, Photoshop, Eclipse and other software. When you press Ctrl+Z during editing, you can undo the current operation and restore the document to its previous state; There are also the back button in IE, rollback operation in database transaction management, intermediate result archiving function when playing games, backup operation of database and operating system, repentance function in chess games, etc.
Memo mode can record the internal state of an object. When the user regrets, it can undo the current operation and restore the data to its original state.
Definition and characteristics of pattern
If you do not need to save the object to the original state of Memento, you can restore the object to the original state of Memento, so that it can be saved outside the original state of Memento. This mode is also called snapshot mode.
Memo mode is an object behavior mode. Its main advantages are as follows.
- Provides a mechanism to restore state. When users need it, they can easily restore the data to a historical state.
- The encapsulation of internal state is realized. Except for the initiator who created it, no other object can access this status information.
- Simplified the human. The initiator does not need to manage and save each backup of its internal status. All status information is saved in the memo and managed by the manager, which is in line with the principle of single responsibility.
Its main disadvantage is: high resource consumption. If the internal state information to be saved is too much or too frequent, it will occupy a large amount of memory resources.
Structure and implementation of pattern
The core of memo mode is to design memo class and manager class for managing memo. Now let's learn its structure and implementation.
1. Structure of the model
The main roles of the memo model are as follows.
- Originator role: record the internal status information at the current time, provide the function of creating memos and recovering memo data, and realize other business functions. It can access all the information in memos.
- Memo role: responsible for storing the internal status of the initiator and providing these internal status to the initiator when necessary.
- Caretaker role: manages memos and provides the function of saving and obtaining memos, but it cannot access and modify the contents of memos.
The structure diagram of memo mode is shown in Figure 1.
Figure 1 structure diagram of memo mode
2. Implementation of mode
The implementation code of memo mode is as follows:
package memento; public class MementoPattern { public static void main(String[] args) { Originator or=new Originator(); Caretaker cr=new Caretaker(); or.setState("S0"); System.out.println("Initial state:"+or.getState()); cr.setMemento(or.createMemento()); //Save status or.setState("S1"); System.out.println("New status:"+or.getState()); or.restoreMemento(cr.getMemento()); //Restore state System.out.println("Restore state:"+or.getState()); } } //memorandum 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; } } //Sponsor 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()); } } //controller class Caretaker { private Memento memento; public void setMemento(Memento m) { memento=m; } public Memento getMemento() { return memento; } }
The results of program operation are as follows:
Initial state:S0 New status:S1 Restore state:S0
Application examples of pattern
[example 1] design a blind date game using memo mode.
Analysis: if there are four beauties Xi Shi, Wang Zhaojun, Diao Chan and Yang Yuhuan on a blind date with you, 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 I hope you don't spend too much time; This game provides regret function. It is more appropriate to use "memo mode" design( Click here to download the pictures of the four beauties to be displayed).
First of all, a Girl class is designed. It is a memo role, which provides the function of obtaining and storing beauty information; Then, a blind date (You) class is designed, which is the initiator role. It records the internal status information (the name of the temporary wife) at the current time, and provides the function of creating memos and restoring memo data; Finally, define a GirlStack class, which is a manager role, responsible for managing memos, and is used to save the beauty information previously selected by a blind date (You), but it can only save up to 4, providing regret function.
The client class is designed as a form program, which includes a GirlStack object and a blind date object. It implements the event processing method actionPerformed(ActionEvent e) of the ActionListener interface, and displays the four beauty images and the beauty images selected by the blind date (You) in the form. Figure 2 shows its structure.
Figure 2 structure diagram of blind date game
The program code is as follows:
package memento; import java.awt.GridLayout; import java.awt.event.*; import javax.swing.*; public class DatingGame { public static void main(String[] args) { new DatingGameWin(); } } //Customer form class 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("Using memo mode to design blind date game"); you=new You(); girls=new GirlStack(); this.setBounds(0,0,900,380); this.setResizable(false); FileName="src/memento/Photo/Four beauties.jpg"; g=new JLabel(new ImageIcon(FileName),JLabel.CENTER); CenterJP=new JPanel(); CenterJP.setLayout(new GridLayout(1,4)); CenterJP.setBorder(BorderFactory.createTitledBorder("The four beauties are as follows:")); CenterJP.add(g); this.add("Center",CenterJP); EastJP=new JPanel(); EastJP.setLayout(new GridLayout(1,1)); EastJP.setBorder(BorderFactory.createTitledBorder("Your chosen lover is:")); this.add("East",EastJP); JPanel SouthJP=new JPanel(); JLabel info=new JLabel("The four beauties have "the appearance of sinking fish and falling geese, and the appearance of closing the moon and ashamed of flowers". Who do you choose?"); girl1=new JRadioButton("Xi Shi",true); girl2=new JRadioButton("army officer's hat ornaments"); girl3=new JRadioButton("Wang Zhaojun"); girl4=new JRadioButton("Yang Yuhuan"); button1=new JButton("determine"); button2=new JButton("return"); 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("blank"); you.setWife("blank"); girls.push(you.createMemento()); //Save status } //display picture void showPicture(String name) { EastJP.removeAll(); //Clear panel contents EastJP.repaint(); //Refresh screen 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()); //Save status if(ok && girl1.isSelected()) { showPicture("Xi Shi"); } else if(ok && girl2.isSelected()) { showPicture("army officer's hat ornaments"); } else if(ok && girl3.isSelected()) { showPicture("Wang Zhaojun"); } else if(ok && girl4.isSelected()) { showPicture("Yang Yuhuan"); } } else if(e.getSource()==button2) { you.restoreMemento(girls.pop()); //Restore state showPicture(you.getWife()); } } } //Memo: Beauty 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; } } //Sponsor: you class You { private String wifeName; //wife 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()); } } //Manager: Beauty stack 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("You are too careless. You change from one place to another!"); return false; } else { girl[++top]=p; return true; } } public Girl pop() { if(top<=0) { System.out.println("The beauty stack is empty!"); return girl[0]; } else return girl[top--]; } }
The running results of the program are shown in Figure 3.
Figure 3 running results of blind date game( Click here to view the original image)
Application scenario of pattern
Having learned the definition, characteristics, structure and implementation of memo pattern, let's look at the following application scenarios of this pattern.
- Scenes that need to save and restore data, such as the archiving function of intermediate results when playing games.
- It is necessary to provide a scenario that can roll back operations, such as Word, Notepad, Photoshop, Eclipse and other software. Press Ctrl+Z during editing, as well as transaction operations in the database.
Mode extension
In the memo mode described earlier, there are examples of single state backup and multi state backup. The following describes how the memo mode is the same as Prototype mode Mixed use. In the memo mode, the information of the "initiator" is backed up by defining the "Memo", while the clone() method of the prototype mode has the function of self backup. Therefore, if the initiator implements the clonable interface, it has the function of backing up itself. At this time, the memo class can be deleted, and its structure is shown in Figure 4.
Fig. 4 structure diagram of memo mode with prototype
The implementation code is as follows:
Plain text copy package memento; public class PrototypeMemento { public static void main(String[] args) { OriginatorPrototype or=new OriginatorPrototype(); PrototypeCaretaker cr=new PrototypeCaretaker(); or.setState("S0"); System.out.println("Initial state:"+or.getState()); cr.setMemento(or.createMemento()); //Save status or.setState("S1"); System.out.println("New status:"+or.getState()); or.restoreMemento(cr.getMemento()); //Restore state System.out.println("Restore state:"+or.getState()); } } //Initiator prototype 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; } } //Prototype Manager class PrototypeCaretaker { private OriginatorPrototype opt; public void setMemento(OriginatorPrototype opt) { this.opt=opt; } public OriginatorPrototype getMemento() { return opt; } }
The running results of the program are as follows:
Initial state:S0 New state:S1 Restore state:S0 pportedException e) { e.printStackTrace(); } return null; } } //Prototype Manager class PrototypeCaretaker { private OriginatorPrototype opt; public void setMemento(OriginatorPrototype opt) { this.opt=opt; } public OriginatorPrototype getMemento() { return opt; } }
The running results of the program are as follows:
Initial state:S0 New status:S1 Restore state:S0