Presentation is loading. Please wait.

Presentation is loading. Please wait.

Unit 31 Memento Summary prepared by Kirk Scott 1.

Similar presentations


Presentation on theme: "Unit 31 Memento Summary prepared by Kirk Scott 1."— Presentation transcript:

1 Unit 31 Memento Summary prepared by Kirk Scott 1

2 Design Patterns in Java Chapter 19 Memento Summary prepared by Kirk Scott 2

3 The Introduction Before the Introduction This chapter is better than the last one As usual, the authors are performing a balancing act They want concrete examples that are somehow related to fireworks The benefit of this is that the whole book is based on one monolithic example, in effect 3

4 The disadvantage is that to present even relatively simple design patterns, there may be a lot of domain specific machinery that needs to be explained along the way 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 4

5 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 5

6 Specifically, the book’s examples are based on adding an undo feature to the graphic visualization of a factory which was introduced in chapter 17 In order to support undo, whenever a change is made to the state of the visualization, a copy of the current state is saved When the undo selection is made, the current state is replaced by the most recently saved state 6

7 Book definition: The intent of the Memento pattern is to provide storage and restoration of an object’s state 7

8 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 8

9 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? 9

10 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 10

11 11

12 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 12

13 13

14 The book describes the state that needs to be captured as follows: 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 14

15 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 15

16 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 16

17 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 17

18 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 18

19 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 19

20 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 However, there is little doubt in my mind that coding the logic for undoing would be considerably more complex than the book’s approach of simply restoring the list of previous machine locations wholesale 20

21 The book suggests that overall the visualization can be structured using a model- view-controller type design This is valid, but it is not critical to understanding the Memento design pattern The MVC pattern will be touched only to the extent necessary to move through the book’s presentation of the Memento design pattern 21

22 It might be useful to look at the complete application code in order to understand the MVC pattern and its implementation better, but this is not my purpose in going through the chapter A UML diagram is given on the next 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 (part of the MVC pattern) will be outlined afterwards 22

23 23

24 The basic idea to take away from the UML diagram these simple observations: When the user adds or moves a machine in the visualization The factory model should change accordingly, the appearance of the visualization should be updated, and the state should be saved 24

25 When the user clicks Undo The previous state should be restored to the model and the appearance of the visualization should be updated 25

26 Needless to say, the application reacts to these 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 Again, strictly speaking, how the application deals with events is extraneous to the new design pattern under consideration, Memento 26

27 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 27

28 28

29 In the previous UML diagram, the Stack and ArrayList were brought out as separate boxes There was something of no less importance that should be brought out A memento itself is implemented as something typed as List, or as it will turn out, more specifically as an instance of ArrayList The memento is an ArrayList which holds the points specifying the locations of the machines in the work area for a given application state 29

30 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 next overhead 30

31 public class FactoryModel { private Stack mementos; private ArrayList listeners = new ArrayList(); public FactoryModel() { mementos = new Stack(); mementos.push(new ArrayList()); } … 31

32 Most of the code shown is unremarkable The most important thing to notice is this line of code: mementos.push(new ArrayList()); As stated above, the literal 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 is pushed onto the stack 32

33 Notice that in general, there is no need for a state to be named, and 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 33

34 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 Code for the FactoryModel add() method is shown on the next 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 34

35 public void add(Point location) { List oldLocs = (List) mementos.peek(); List newLocs = new ArrayList(oldLocs); newLocs.add(0, location); mementos.push(newLocs); notifyListeners(); } 35

36 It is possible to iterate over ArrayLists without worrying about the order of their contents The ArrayList class has “Array” in its name because it is also possible to treat the contents as ordered 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 36

37 On the next overhead, the code for the getLocations() method is given It is very simple The reason for having such a method is to support those parts of the application that respond to events Repainting the work area will require access to all of the current machine locations, which are returned by this method 37

38 public List getLocations() { return (List) mementos.peek(); } 38

39 Next the book considers the undo() method in the FactoryModel class This, obviously, 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 39

40 Challenge 19.1 Write the code for the FactoryModel class’s undo() method. 40

41 Solution 19.1 Here is one implementation of undo() for FactoryModel [See the code on the next 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 41

42 public boolean canUndo() { return mementos.size() > 1; } public void undo() { if(!canUndo()) return; mementos.pop(); notifyListeners(); } 42

43 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. 43

44 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. 44

45 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 45

46 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 46

47 An expanded UML diagram showing the relationships between the FactoryModel, Visualization, and VisMediator classes will be shown shortly The Visualization class, like in the example of the previous chapter, 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 47

48 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 48

49 49

50 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 50

51 protected JButton undoButton() { if(undButton == null) { undoButton = ui.createButtonCancel(); undoButton.setText(“Undo”); undoButton.setEnabled(false); undoButton.addActionListener(mediator.undoAction()); } return undoButton; } 51

52 In summary, the previous code shows that the mediator is the listener for a button in the Visualization GUI 52

53 The book states that the mediator then informs the factory of requested changes using the code shown on the following overhead I am tempted to believe that there is a typo in the book The name of the method in the VisMediator class in the previous UML diagram is undoAction The code is shown on the following overhead, where the method name is given simply as undo() 53

54 private void undo(ActionEvent e) { factoryModel.undo(); } 54

55 In summary, the previous code shows that the mediator can affect the factory model This is possible because the construction of an instance of VisMediator takes an instance of the factory model The circle of relationships is made complete by adding the instance of the Visualization as a change listener to the factory These last two connections are accomplished in the constructor for Visualization, shown on the next overhead 55

56 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); } 56

57 If the VisMediator listens to the GUI And the VisMediator has access to change the FactoryModel And the Visualization listens to the FactoryModel Then, for example, the sequence of events when the Undo button is clicked in the GUI can be modeled as shown in the following UML diagram 57

58 58

59 The Visualization can listen to the FactoryModel A change in the FactoryModel is propagated to the Visualization by calling the stateChanged() method on it 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 59

60 Challenge 19.2 Write the stateChanged() method for the Visualization class. 60

61 Solution 19.2 One solution is: [See code on the next overhead.] 61

62 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(); } 62

63 I 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 63

64 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 64

65 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 65

66 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 66

67 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 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 67

68 Challenge 19.3 Write down two reasons that might drive you to save a memento in a file rather than as an object. 68

69 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. 69

70 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.] 70

71 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 71

72 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 72

73 73

74 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 74

75 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 75

76 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); } 76

77 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; } 77

78 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); } 78

79 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 79

80 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) 80

81 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 81

82 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()); } }; } 82

83 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(); } 83

84 Challenge 19.4 Write the code for the restoreAction() method of the VisMediator class 84

85 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 85

86 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 86

87 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(); } 87

88 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.” 88

89 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. 89

90 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. 90

91 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. 91

92 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. 92

93 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? 93

94 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 94

95 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 95

96 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 96

97 The End 97


Download ppt "Unit 31 Memento Summary prepared by Kirk Scott 1."

Similar presentations


Ads by Google