Chapter 19
Memento
Summary prepared by Kirk Scott
1
2
3
4
Design Patterns in Java
Chapter 19
Memento
Summary prepared by Kirk Scott
5
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
• 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
• 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
• Book definition:
• The intent of the Memento pattern is to
provide storage and restoration of an object’s
state
9
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
• 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
• On the next overhead the graphical
visualization of a factory is shown at software
start-up
• Its state is currently empty—but it’s important
to note that empty is a state
• The Add button is active
• The Undo button is disabled because nothing
has been added yet
12
13
• 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
• The scenario under discussion is one of run-time
functionality
• The state that needs to be captured is a list of the
locations of the machines that the user has
placed in the application at a given time
• One instance of such a list is one memento
• A history of multiple states, multiple mementos,
can be stored in a stack
• Clicking the Undo button means popping the
stack
16
• 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.
• The previous state, which is now at the top of
the stack, will be restored
17
• 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
Comment
• 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
Comment
• 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
Comment
• Instead, complete states are saved
• Then undoing simply means restoring the
previous state
• There is a lot of redundancy in storing all of
the previous states in this way
• The benefit is in the straightforward meaning
and implementation of the undo function
21
What the Book Does Next
• The book gives an initial solution
• It then modifies that solution
• The solutions illustrate a particular coding
technique which isn’t part of the pattern but
which deserves explanation
22
The Book’s First Solution
• On the overhead following the next one, a
UML diagram of the FactoryModel class is
shown
• It has a reference to an instance of the Stack
and ArrayList classes (classes in the Java API)
• The stack will hold the mementos
23
• The FactoryModel class also has a reference to
an ArrayList
• This holds the listeners for the graphical
components of the application
• This design feature is a sideshow
• It will not be discussed
• The goal is to get to memento
24
25
Implementing Memento in the First
Example
• What is a memento?
• It is an ArrayList which holds the points
specifying the locations of the machines in the
work area for a given application state
• The stack in the FactoryModel potentially
holds multiple instances of such ArrayLists
26
• Here is the code at the beginning of the
FactoryModel class
• It shows the declarations of the Stack of
mementos
• It also shows the default constructor
• In it the Stack is constructed
• The initial, empty state (empty ArrayList) is
constructed and pushed onto the stack
27
• public class FactoryModel
• {
•
private Stack mementos;
•
private ArrayList listeners = new ArrayList();
•
public FactoryModel()
•
{
•
mementos = new Stack();
•
mementos.push(new ArrayList());
•
}
• …
28
Ordering of mementos
• States are not named
• The identifying feature of states which is
important to the application is where in the
stack they occur, since a stack is an ordered
data structure
• In other words, going down the stack means
going back in time
29
• 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
30
Adding a Machine to the
Representation
• 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, the listeners are
notified
• Comments have been added to the code
31
•
•
•
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();
/*
•
•
/*
•
•
Add the new location to the new state.
*/
newLocs.add(0, location);
/*
•
•
*/
List newLocs = new ArrayList(oldLocs);
•
•
Create a new state, the same as the old.
Push the new state onto the stack.
*/
mementos.push(newLocs);
/*
Notify the listeners of changes to the state.
*/
notifyListeners();
}
32
Ordering in Mementos
• It is possible to iterate over ArrayLists 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 ArrayList at position 0
33
• What’s happening here is a version of the
painter’s algorithm
• Each succeeding machine and location that
becomes part of a state is put “on top”
• That way, if visual representations overlap, the
thing that is “on top” of the ArrayList will be
displayed on top of the other representations
in the GUI
34
Getting All Locations for a Current
State
• 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
35
• public List getLocations()
• {
•
return (List) mementos.peek();
• }
36
Implementing Undo Functionality
• 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 notify any listeners
• The book deals with this method as a
challenge
• As usual, the answer will just be given
37
•
•
•
•
•
•
•
•
•
•
public boolean canUndo()
{
return mementos.size() > 1;
}
public void undo()
{
if(!canUndo()) return;
mementos.pop();
notifyListeners();
}
38
Working Towards the Next Design
• A UML diagram is given on the following
overhead showing how the factory model,
visualization, and VisMediator are
implemented in separate classes
• The fundamental idea is that a better design
will localize responsibility for the model, view,
and controller in different classes
• Discussion will follow the diagram
39
40
• The application reacts to events by means of a
mouse listener in the work area and listeners
for the Add and Undo buttons
• The VisMediator contains the functionality
that responds to events in the GUI
• The VisMediator contains the controller
functionality that makes updates based on the
events
41
• The book expresses the function of the
VisMediator class in this way:
• “The mediator translates GUI events into
factory changes.”
• An expanded UML diagram of the design is
shown on the following overhead
• It repeats the relationships, shown earlier, and
includes methods for two of the classes
42
43
Code
• The book then presents some code for this
design
• The code is heavily dependent on Java
swing—and for that reason its details are not
of great interest and will not be presented
• In the homework for this section alternative
code will be developed
44
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
• Some of the book’s observations and
examples will be presented
45
• If state is to be stored between sessions, the
period of time involved could range from days,
to weeks, to months, to years…
• State can be saved in the form of a persistent
serializable object, or perhaps a text string or
other data in secondary storage
• Not only can users start and stop
• You can provide archival storage plus the
ability to restart on a different system
46
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…”
• A screen shot showing these menu options is
given on the following overhead
47
48
Implementation
• Again, the book’s code is heavily depending on
Java swing
• This code will not be pursued in detail
• The important point is the use of serializability
49
• What is being saved in serializable form is the
list of locations representing the current state
of the visualization
• The goal of saving is not to save a complete
history of all states
• It would be up to the user to name each
separate state as it’s saved, and restore it by
name later, if desired
50
• 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
51
• Code for the save() method from the book is
shown on the following overhead
• It shows the syntax for doing I/O with serializable
objects
• Any object that you want to save in this way has
to implement the Serializable interface
• This is a marker interface
• The requirement is that for any class to be
serializable, any object it contains also has to be
serializable
52
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
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();
}
}
53
• The corresponding restore() method is shown
on the following overhead
• When saving and restoring, there is no
mystery to the order
• If items were saved (written to a file) in the
order A, B, C, then they will be restored (read
back from the file) in the order A, B, C
54
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
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();
}
}
55
The End
56
© Copyright 2026 Paperzz