Download presentation
Presentation is loading. Please wait.
Published byReynold Fields Modified over 9 years ago
1
Unit 31 Memento Summary prepared by Kirk Scott 1
2
2
3
3
4
4
5
Design Patterns in Java Chapter 19 Memento Summary prepared by Kirk Scott 5
6
The Introduction Before the Introduction This is a succinct preview summary of the memento examples: 1. You can save the state of a running application in a stack data structure 2. You can also save the state of an application in secondary storage using serializability 6
7
It’s worth noting again that there is some utility in the authors’ emphasis on intent Structurally, there is no close relationship between a stack and serializability However, in their respective contexts, transient vs. persistent storage, they can both be used in order to accomplish the same thing 7
8
The book’s examples are based on adding an undo feature to the graphic visualization of a factory Whenever a change is to be made to the state of the visualization, a copy of the current state is saved before the change is made When the undo option is selected, the current state is replaced by the most recently saved state 8
9
Book definition: The intent of the Memento pattern is to provide storage and restoration of an object’s state 9
10
A Classic Example: Using Memento for Undo A memento may be as simple as a single object that holds an application’s state It may also turn out that some collection of objects or some data structure (like a stack) is involved in implementing the memento pattern 10
11
From a practical point of view, these kinds of questions have to be answered: How will state be captured in a memento? When will the state be captured? How will the previous state be restored based on the contents of the memento? 11
12
On the next overhead the visualization is shown at start up Its state is currently empty—but it’s important to note that empty is a state Since nothing has been done yet, the Undo button is disabled 12
13
13
14
The next overhead shows the application after a few machines have been added and dragged around the work area Note that the Undo button is no longer disabled 14
15
15
16
The state that needs to be captured is a list of the locations of the machines that the user has placed in the application The scenario under discussion is one of run- time functionality The book suggests keeping a list of locations, each list being a memento, on a stack Clicking the Undo button means popping the stack 16
17
In particular, the book outlines the functionality in this way: 1. Each time the user takes an action like add or move, a memento will be created and pushed onto the stack 2. Each time the user clicks Undo, the stack will be popped, removing the current state, and the state will be restored to the previous state, which is now at the top of the stack 17
18
At start-up time, a memento of the empty state will be pushed onto the stack The visualization always has a state and the stack will never be empty The Undo button will be disabled when the stack only has a single entry in it It will not be possible to pop the empty state off of the stack 18
19
Comment mode on: The book hasn’t stated how the list of machine locations will be saved yet, but strictly speaking, such a list is the literal memento in the application The stack is used in order to manage a collection of potentially more than one memento 19
20
Comment mode, continued: The book’s approach may not be elegant, but it’s straightforward Notice that they aren’t trying to save a list of actions, for example This means that it’s not necessary to figure out how to undo an action 20
21
Comment mode, continued: Instead, complete states are saved Then undoing simply means restoring the previous state I would note that there seems to be a lot of redundancy in storing all of the previous states in this way 21
22
I suspect that it would be possible to model state as a sequential collection of machines and a sequence of actions taken on them This might result in less redundancy among the mementos The code for undoing would be considerably more complex than simply restoring the list of previous machine locations 22
23
The book suggests that overall the visualization can be structured using a model-view-controller type design A UML diagram is given on the following overhead showing how the visualization and the factory model are implemented in separate classes The meaning of the VisMediator class and the various relationships shown will be outlined afterwards 23
24
24
25
The UML diagram is supposed to illustrate what happens when the user interacts with the visualization: When a machine is added or moved, the factory model should change accordingly, The appearance of the visualization should be updated, The state should be saved 25
26
When the user clicks Undo the previous state should be restored to the model The appearance of the visualization should also be updated when this happens 26
27
The application reacts to events by means of a mouse listener in the work area and listeners for the Add and Undo buttons Part of the role of the VisMediator class is to hold the functionality that responds to events In other words, the VisMediator contains the controller functionality 27
28
On the next overhead, a UML diagram of the Factory Model class is shown with references to instances of the Stack and ArrayList classes The stack holds the mementos The instance of ArrayList holds the listeners for the graphical components of the application 28
29
29
30
Point number one about the diagram/design is the ArrayList of listeners This neither good nor bad, but it’s probably unnecessary in an application this small Unfortunately, it is also a potential source of confusion 30
31
The diagram doesn’t show it, but we will also be interested in what kinds of things will be stored on the stack In other words, what is a memento It will turn out that a memento is an ArrayList of which holds the points specifying the locations of the machines in the work area for a given application state The mementos shouldn’t be confused with the ArrayList of listeners 31
32
Next the book shows some partial code to give an idea of how the FactoryModel class works The beginning declarations and the default constructor are shown on the following overhead 32
33
public class FactoryModel { private Stack mementos; private ArrayList listeners = new ArrayList(); public FactoryModel() { mementos = new Stack(); mementos.push(new ArrayList()); } … 33
34
Most of the code shown is unremarkable The most important thing to notice is this line of code: mementos.push(new ArrayList()); A memento is an instance of ArrayList When the model is constructed, the empty state is put onto the stack The default constructor is used to create an empty ArrayList and push it onto the stack 34
35
Notice that in general, there is no need for a state to be named The states are not named instances of objects They are simply instances of ArrayList constructed at the moment Their identifying feature which is important to the application is where in the stack they occur, since a stack is an ordered data structure 35
36
The book summarizes the rest of the methods in the FactoryModel class as follows: They maintain the stack of mementos They deal with events that make changes 36
37
Code for the FactoryModel add() method is shown on the following overhead, for example Adding a machine to the visualization means adding a point to the list of machine locations When this change occurs, any listeners have to be notified Comments have been added to the code 37
38
public void add(Point location) { /* Get a copy of the old state by peeking at the top of the stack of mementos. */ List oldLocs = (List) mementos.peek(); /* Create a new state, the same as the old. */ List newLocs = new ArrayList(oldLocs); /* Add the new location to the new state. */ newLocs.add(0, location); /* Push the new state onto the stack. */ mementos.push(newLocs); /* Notify the listeners of changes to the state. */ notifyListeners(); } 38
39
It is possible to iterate over lists without worrying about the order of their contents It is also possible to refer to elements of the list by index In the previous method, a location was added to a memento list at position 0 The idea here is that if things overlap in the visualization, those things most recently added will be displayed on top 39
40
The code for the getLocations() method is given on the following overhead Responding to events and repainting the work area will require access to all of the current machine locations The method returns the list of current machine locations—the list at the top of the memento stack Notice that peek() is not the same as popping the stack 40
41
public List getLocations() { return (List) mementos.peek(); } 41
42
Next the book considers the undo() method in the FactoryModel class This is the method that triggers a change in state back to the previous one Like the add() method given above, the undo() method will have to notify any listeners The book deals with this method as a challenge 42
43
Challenge 19.1 Write the code for the FactoryModel class’s undo() method. 43
44
Solution 19.1 Here is one implementation of undo() for FactoryModel [See the code on the following overhead] Comment mode on: It is not clear to me why the authors have broken the implementation into two tiny methods It’s clear how it works It’s also clear how the two could easily be merged 44
45
public boolean canUndo() { return mementos.size() > 1; } public void undo() { if(!canUndo()) return; mementos.pop(); notifyListeners(); } 45
46
Solution 19.1, continued: This code is careful to ignore undo() requests if the stack is down to its initial state with a single memento. The top of the stack is always the current state, so the undo() code has to pop the stack to expose the previous memento. 46
47
Solution 19.1, continued: When you write a createMemento() method, you should convince yourself or your colleagues that the method returns all the information necessary to reconstruct the receiving object. In this example, a machine simulator can reconstruct itself from a clone, and a factory simulator can reconstruct itself from a list of machine simulator clones. 47
48
Solution 19.1 Comment mode on What the authors are trying to say in the previous paragraph is not clear They have claimed that the only memento you need for this application is a list of machine locations Presumably, the picture of each machine in the visualization is just a stock image Why they’re now babbling about clones and lists of clones is not clear 48
49
Back to the material in the text: The previous UML diagram and code examples gave some idea of the FactoryModel class It contains methods that change the state of the model It also contains methods to register listeners and notify them when the state changes 49
50
An expanded UML diagram showing the relationships between the FactoryModel, Visualization, and VisMediator classes will be shown shortly The Visualization class has methods related to creating the GUI of the application It can respond to changes in the factory model in order to update the graphical representation 50
51
The VisMediator class is the locus for listening In other words, handling GUI events is offloaded into this new class The book expresses the function of the VisMediator class in this way: “The mediator translates GUI events into factory changes.” The relationships are shown in the UML diagram on the following overhead 51
52
52
53
The book now shows the relationship between the Visualization class and the VisMediator class in more detail by considering code The Visualization class creates an Undo button and adds to it a listener belonging to the VisMediator class This is shown on the next overhead 53
54
protected JButton undoButton() { if(undoButton == null) { undoButton = ui.createButtonCancel(); undoButton.setText(“Undo”); undoButton.setEnabled(false); undoButton.addActionListener(mediator.undoAction()); } return undoButton; } 54
55
In summary, the previous code shows that the mediator is the listener for a button in the Visualization GUI 55
56
The book states that the mediator then informs the factory of requested changes using the code shown on the following overhead In other words, undo() is the name of the action method that belongs to the listener This matches the name of the method called on the factory model 56
57
private void undo(ActionEvent e) { factoryModel.undo(); } 57
58
The mediator can affect the factory model because the construction of an instance of VisMediator takes an instance of the factory model as a parameter An instance of the Visualization is added as a change listener to the factory The constructor for Visualization is shown on the following overhead The middle two lines of code show the construction of the VisMediator and the adding of the listener 58
59
public Visualization(UI ui) { super(new BorderLayout)); this.ui = ui; mediator = new VisMediator(factoryModel); factoryModel.addChangeListener(this); add(machinePanel(), BorderLayout.CENTER); add(buttonPanel(), BorderLayout.SOUTH); } 59
60
The VisMediator listens to the GUI The VisMediator has access to change the FactoryModel The Visualization listens to the FactoryModel The sequence of events when the Undo button is clicked in the GUI can be modeled as shown in the following sequence diagram 60
61
61
62
The Visualization can listen to the FactoryModel A change in the FactoryModel is propagated to the Visualization by calling the stateChanged() method on it 62
63
A state change, like undo, means that all of the current pictures of machines have to be removed from the Visualization Then pictures at all of the locations in the previous state have to be presented The Undo button has to be enabled/disabled according to whether a further undo is possible 63
64
Challenge 19.2 Write the stateChanged() method for the Visualization class. 64
65
Solution 19.2 One solution is: [See code on the next overhead.] 65
66
public void stateChanged(ChangeEvent e) { machinePanel().removeAll(); List locations = factoryModel.getLocations(); for(int i = 0; i < locations.size(); i++) { Point p = (Point) locations.get(i); machinePanel().add(createPictureBox(p)); } undoButton().setEnabled(factoryModel.canUndo()); repaint(); } 66
67
Note two things in the previous code: When generating the visual representation, the list of locations is traversed in order In other words, a for loop, not a for each loop is used This makes sure that the most recent machine images are on top 67
68
Also, there is a createPictureBox() method that we haven’t seen before This apparently is the method that generates the standard representation of a machine in the visualization 68
69
The book’s summary of the foregoing example is this: Mementos, records of visualization state, are being stored as objects in a stack while the program is running It is also possible that more persistent storage of state may be desirable 69
70
Memento Durability This subsection can be summarized very succinctly If you want persistent storage of state, in Java the solution is to save memento objects in secondary storage using serializability In the interests of completeness, the book’s observations and examples will be presented 70
71
The book observes that it may be desirable to store state over widely varying periods of time The previous example was about storing it during the course of a program run A program run can be referred to as a session 71
72
If state is to be stored between sessions, the period of time involved could range from days, to weeks, to months, to years… The book also observes that it may be possible to save state in the form of a transient, run- time object, a serializable object in secondary storage, or perhaps, a string in secondary storage 72
73
Challenge 19.3 Write down two reasons that might drive you to save a memento in a file rather than as an object. 73
74
Solution 19.3 Storing a memento as an object assumes that the application will still be running when the user wants to restore the original object. Reasons that will force you to save a memento to persistent storage include the following. 74
75
The ability to restore an object’s state has to survive a system crash. You anticipate that the user will exit the system and will want to resume work later. You need to reconstruct an object on another computer. [End of Solution 19.3.] 75
76
Persisting Mementos Across Sessions The book next proposes a new visualization, Visualization2, which is a subclass of the original visualization Visualization2 will have menu options to “Save As…” and “Restore From…” These are analogous to the save and load features of Togiz Kumalak from CS 202 76
77
The domain specific difference is simply in what’s being saved and restored There are also potentially minor syntactical differences in how the authors implement the listeners compared to the model used by the orange book (CS 202) A screen shot showing these menu options is given below 77
78
78
79
On the overhead following the next one, code for the new Visualization2 class is given In that code you will notice that the listeners for the menu options come from the VisMediator The code for VisMediator will be pursued after the code for Visualization2 79
80
Depending on how closely you’re following the book’s materials, the following observations may also be important In addition to the printed code in the text, source code can be downloaded from the book’s Web site Unfortunately, the Visualization2 and VisMediator code on the Web site differ from that given in the book What is presented here is based on the printed version in the text 80
81
package com.oozinoz.visualization; import java.awt.event.*; import javax.swing.*; import com.oozinoz.ui.*; public class Visualization2 extends Visualization { public Visualization2(UI ui) { super(ui); } 81
82
public JMenuBar menus() { JMenuBar menuBar = new JMenuBar(); JMenu menu = new JMenu("File"); menuBar.add(menu); JMenuItem menuItem = new JMenuItem("Save As..."); menuItem.addActionListener(mediator.saveAction()); menu.add(menuItem); menuItem = new JMenuItem("Restore From..."); menuItem.addActionListener(mediator.restoreAction()); menu.add(menuItem); return menuBar; } 82
83
public static void main(String[] args) { Visualization2 panel = new Visualization2(UI.NORMAL); JFrame frame = SwingFacade.launch(panel, "Operational Model"); frame.setJMenuBar(panel.menus()); frame.setVisible(true); } 83
84
By this time it’s possible to have forgotten what, exactly, you’re saving What is being saved in serializable form are the lists of locations representing the current state of the visualization There is no stack present It would be up to the user to name each separate state as it’s saved, and restore it by name later, if desired 84
85
On the overhead following the next one, the code for the saveAction() method of the VisMediator is given This is the method that is called in Visualization2 in order to add a listener to the menu item The book uses an anonymous listener (unfortunately) 85
86
This anonymous listener relies on a save() method in VisMediator, which is also shown It is this method that finally does the actual work of saving using serializability You may want to take a look at the code as presented on the Web site It makes the relationship between the Visualization2 and VisMediator classes clearer The code from the text is given on the following overheads 86
87
public ActionListener saveAction() { return new ActionListener() { public void actionPerformed() { try { VisMediator.this.save((Component)e.getSource()); } catch(Exception ex) { System.out.println(“Failed save: “ + ex.getMessage()); } }; } 87
88
public void save(Component source) throws Exception { JFileChooser dialog = new JFileChooser(); dialog.showSaveDialog(source); if (dialog.getSelectedFile() == null) return; FileOutputStream out = null; ObjectOutputStream s = null; try { out = new FileOutputStream(dialog.getSelectedFile()); s = new ObjectOutputStream(out); s.writeObject(factoryModel.getLocations()); } finally { if (s != null) s.close(); } 88
89
Challenge 19.4 Write the code for the restoreAction() method of the VisMediator class 89
90
Solution 19.4 One solution is: Comment mode on: The challenge asks for the code for the restoreAction() method The solution shows the code for the restore() method, without giving the restoreAction() method 90
91
Comment mode continued: The book notes that the restore() method (not the restoreAction() method, since that’s not shown) is analogous to the save() method It would also be the case that the restoreAction() method would be analogous The code given by the book as a solution is shown on the next overhead 91
92
public void restore(Component source) throws Exception { JFileChooser dialog = new JFileChooser(); dialog.showOpenDialog(source); if (dialog.getSelectedFile() == null) return; FileInputStream out = null; ObjectInputStream s = null; try { out = new FileInputStream(dialog.getSelectedFile()); s = new ObjectInputStream(out); ArrayList list = (ArrayList) s.readObject(); factoryModel.setLocations(list); } finally { if (s != null) s.close(); } 92
93
Continuing with book’s material: The book states that in the original book, Design Patterns, the intent of the Memento design pattern is stated as follows: “Without violating encapsulation, capture and externalize an object’s internal state so that the object can be restored to this state later.” 93
94
Challenge 19.5 In this case, we used Java serialization to write to a file in binary format. Suppose that we had written it to XML format (textual) instead. Write a short statement of whether, in your opinion, saving a memento in textual form would violate encapsulation. 94
95
Solution 19.5 To encapsulate is to limit access to an object’s state and operations. Saving an object, such as a collection of factory [machine] location points, in textual form exposes the object’s data and allows anyone with a text editor to change the object’s state. Thus, saving an object in XML form violates encapsulation, at least to some degree. 95
96
Violation of encapsulation through persistent storage may be a concern in practice, depending on your application. To address this threat, you might limit access to the data, as is common in a relational database. In other cases, you might encrypt the data, as is common when transmitting sensitive HTML text. 96
97
The point here is not whether the words encapsulation and memento apply to a design but rather the real importance of ensuring data integrity while supporting the data’s storage and transmission. 97
98
Comment mode on: This is my take on what the authors have just said: The original question about storing in textual form is a red herring First of all, you might ask, why store object state in textual form when Java serializability is available anyway? 98
99
Secondly, their follow-up observation is essentially this: Even if you use serializability, somebody with a binary editor could still mess with the state of a stored object Ultimately, if you are going to save things in secondary storage, and security is a concern, you will have to limit access to the data 99
100
Another Example No other example will be given 100
101
Lasater’s UML Lasater’s UML diagram is included for the sake of completeness It doesn’t seem to add anything to understanding the pattern 101
102
102
103
Summary The Memento design pattern lets you capture an object’s state so that the object can be restored later The need to use the memento pattern is most frequently occasioned by the need to support an “undo” function in an application In this case, the state may be saved in an object which is part of the program and only persists as long as the program is running 103
104
It may also be desirable to be able to save and restore the state of an object between program runs Potentially, such storage can persist for long periods of time Typically, the solution is to save a representation of the object to secondary storage Java serializability supports this capability 104
105
The End 105
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.