unit 30 observer summary prepared by kirk scott 1
TRANSCRIPT
1
Unit 30Observer
Summary prepared by Kirk Scott
2
Design Patterns in JavaChapter 9Observer
Summary prepared by Kirk Scott
3
The Introduction Before the Introduction
• The book’s logic of organizing patterns by intent puts the Observer pattern relatively early
• The Observer pattern actually leads to a more complex, large-scale pattern, the Model-View-Controller pattern
• Formally, the book doesn’t “cover” this pattern, but the reality is that that is where the chapter ends
4
• The upshot of the matter is that the book sort of jumps into deep water quickly
• The purpose of this introduction before the introduction is to provide some context
• I refer back to some of the things that happened in CS 202 that might be relevant to understanding what the book is talking about now
5
• Think back to Wari and Togiz Kumalak• The very first implementations weren’t
graphical at all• The second stage of implementation grew into
hand-coded cups represented by rectangles, containing seeds represented by dots
• At this stage, mouse functionality was introduced so that game play was conducted by clicking the mouse
6
• The state of the code at the second stage illustrated several things
• Thinking back to the UML diagrams, they tended to branch in two directions, an input side and an output side
• Thus, the input and output were relatively distinct, but the game itself, that is to say, the state of the board and logic of play was mixed up with the input and output stuff
7
• Taking Togiz Kumalak as an example, this is the Model-View-Controller idea:
• The model part would be the state of the game and the rules of play
• The view part would be the output side of the application
• The controller part would be the input side of the application
8
• The logic of the Model-View-Controller pattern is to cleanly separate these functionalities into different classes
• Although there was some separation in Togiz Kumalak, it didn’t come close to a pure model-view-controller design
• In spite of the two branches of the design, things were still mixed together
9
• In Togiz Kumalak on the input side you had listeners
• It turns out that the concept of “listening” is critical to the use of the Observer and Model-View-Controller patterns
• Listeners with a method like actionPerformed(Event anEvent) were added to the code, and they were notified of events
10
• Not only is this built into Java in the form of the listeners already seen
• By the end of the chapter the book is explaining that Java contains an interface named Observer and a class named Observable
• The idea is that in your own code, you can write classes that have the ability to be notified of events occurring with objects of other classes
• This can be useful when writing a graphical application even just a little bit more complicated than Togiz Kumalak
11
• At the second stage of the development of Togiz Kumalak, on the output side you had graphical representations of hand-coded graphical objects
• The key result of this fact is that when the state of the game changed, it was necessary to call repaint() in order to update the on-screen representation
• This introduced the idea of a callback sequence• In other words, you had to write a paintComponent()
method, but you never called it directly• You relied on the system to perform a callback sequence
when you called repaint
12
• At the third stage of development of Togiz Kumalak (the project), the implementation was changed so that all of the graphical representations were done with system supplied objects
• In other words, the application consisted of a panel containing instances of JButton, JTextField, JLabel, and JTextArea
• This made life considerably easier because whenever the state changed, there was no need to call repaint()
• The system took care of this automatically
13
• Stated simplistically• At stage 2, Togiz Kumalak was 50% system
supplied magic, based on the callback sequence• At stage 3, Togiz Kumalak was 100% system
supplied magic• It was OK, but we basically flailed our way
towards a nice implementation without necessarily having a good conceptual grasp of what we were doing
14
• So, the final version of Togiz Kumalak in CS 202 serves as a take-off point for what happens in this chapter in CS 304
• Not surprisingly, the book illustrates the concepts using an example from Oozinoz, not Togiz Kumalak
• As usual, I’m not incredibly interested in the physics content of their code
• I will basically ignore that• However, it is important to understand the Observer and
Model-View-Controller concepts, and how observability is made available in the Java API
15
• The book’s presentation starts with the basic concept, the Observer pattern, and moves to the Model-View-Controller pattern
• The book tries to illustrate the concept step-by-step
• It starts with a first version of the code, moves on to a second, and then arrives at a third, final version
16
• The book explains the observer concept using the terminology of clients and what it calls “an interesting object”
• The idea is that the clients are objects that need to keep up to date on the state of the interesting object
• There are basically three different models for how this might be accomplished in code
17
• 1. The clients have to regularly check the interesting object for changes
• 2. The interesting object notifies clients of changes in its state where the notification includes information about the new state
• 3. The interesting object notifies clients that its state has changed, but the notification does not contain information about the new state
• In that case, it is up to the clients to take action (if desired) to acquire the information and do something about it
18
• Notice how the third approach matches up with the use of listeners as seen so far
• User actions like clicking the mouse are events• The system activates a call to a listener and passes
it the event• The method in the listener, like actionPerformed(),
can call methods on the event object to find out more about it if desired
• The listener code can take certain actions if desired
19
• There was something else that came up at the end of CS 202 that is relevant to this discussion
• That topic was called multi-casting• In the example code given in unit 28, there was a
single “clear” button and several different registers represented by instances of JTextField
• Each register had its own listener that was notified if the clear button was clicked
• The action each register took was to clear its JTextField when the clear button was clicked
20
• Up to that point, the plan had appeared to be one actionone listener
• Then it became one actionmany listeners• Going back to the terminology of the book,
the situation became one interesting objectmany clients
21
• It now becomes possible to lay the groundwork for the book’s statement of the intent of the Observer design pattern
• We are interested in a situation where you have one interesting object and potentially many client objects
• The book describes this as a dependency relationship, where the clients depend on being notified of the state of the interesting object
22
• Book definition: The intent of the Observer pattern is to define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified so that they can react to the change.
23
• Comment mode on:• If this definition had been given without any
background, you would have been justified in wondering what on earth it was good for
• With the background, you have been informed that the classic case where it appears is in the development of an application with a graphical user interface
24
A Classic Example: Observer in GUIs
• Listeners are the classic example of dependent clients that are notified when an event occurs
• The book is going to develop an example which uses a slider control
• This grows in complexity beyond Togiz Kumalak• This makes the book example good for illustrating the
pattern, but Togiz Kumalak will still be referred to• The idea is that the book’s application will have >1
panel, each of which depends on changes to the slider• See the following overhead
25
26
• The book, as usual, gives a description of the application domain physics involved in the example
• In brief, when a solid rocket motor burns, the burn rate of the rocket changes over time, and the thrust it delivers changes over time as a function of the burn rate
• The situation is partially analogous to the previous example where parametric equations were used
27
• Burn rate is expressed as a function of time, t• It is convenient both mathematically and for the sake
of graphing to normalize t to the range from 0 to 1• Thrust is expressed directly as a function of the burn
rate• The new addition to the scenario is a parameter tpeak
• For what they’re worth, the book’s equations are given on the next overhead
• tpeak will be explained afterwards
28
29
• tpeak represents that point in time in the range from 0 to 1 where the burn rate is at a maximum
• The slider allows the user to change the value of tpeak entered into the graphing equations
• Whenever a change is made, the panels containing the graphs for burn rate and thrust have to be updated
30
• Observe that by definition, the burn rate graph has a maximum at tpeak
• I’m not interested enough in the math and physics to figure it out, but it certainly seems like the thrust graph should and does have a maximum at the same point in time
• As the slider is moved, the graphs should change, with the maximums appearing at the new value for tpeak
31
• If you go out to the assignment folder for this chapter, the third version of the authors’ code is given, unpackaged and with one slight coding change so that it will run in TextPad
• If you run it, you will notice that the real effect of moving the slider is that the positions of the burn rate and thrust curves shift in their panels
• The mathematical reality of the model is that the shapes of the curves don’t change
• Their maximums merely move to the new position specified by the slider
32
• As mentioned, the book develops a design for the application in three stages, moving towards a full-scale model-view-controller implementation
• On the next overhead is the UML diagram for the first design
• This design works• The book explains it, and then uses its
shortcomings as a starting point for the next design
33
34
• The contents of the first design can be verbally summarized as follows
• At the top left there is a listener interface, ChangeListener, with a method stateChanged() with a parameter of type ChangeEvent
• At the lower left is the ShowBallistics class which implements this interface, which will be discussed in more detail momentarily
35
• On the right hand side is the BallisticsPanel class
• It is a subclass of the JPanel class• It makes use of the BallisticsFunction interface
36
• The application here is again structured in a manner similar to the parametric equations example
• When a BallisticsPanel object is created, it is given an instance of a function which represents the graph it is supposed to show
• The BallisticsPanel class has a setTPeak(tPeak:double) method that parameterizes the function to be shown
37
• The ShowBallistics class is the heart of the design
• Although its contents are not very complex, the variety of things in the class may hint at problems with the design
• The ShowBalllistics class contains two instances of the BallisticsPanel class
• There is one panel each for the burn rate and the thrust graphs
38
• The ShowBallistics class contains four methods• burnPanel() returns a reference to an instance
of BallisticsPanel• thrustPanel() returns a reference to an
instance of BallisticsPanel
39
• slider() returns a reference to an instance of JSlider
• valueLabel() returns the numeric value of tpeak that the slider has been moved to
• stateChanged(e:ChangeEvent) implements the method required by the interface ChangeListener
40
• The book makes the following statements about how the application works:
• When the application initializes the slider, it registers itself to receive slider events
• When the slider changes, the application updates the panels and updates the label that shows the value of tpeak
41
Challenge 9.1
• Complete the slider() and stateChanged() methods for ShowBallistics so that the ballistics panels and the tpeak label reflect the slider’s value.
• Comment mode on:• The given blocks of incomplete code will be shown on the
next overheads, interleaved with solutions• As usual, based on the amount of information given in the
text so far, it would be difficult to complete the challenge on your own
• The only alternative is the standard one: Look at the book’s solution and try to figure out what it means
42
Challenge 9.1, part 1, provided incomplete code for slider()
• public JSlider slider()• {• if(slider == null)• {• slider = new JSlider();• sliderMax = slider.getMaximum();• sliderMin = slider.getMinimum();• slider.addChangeListener( ?? );• slider.setValue(slider.getMinimum());• }• return slider;• }
43
• Before looking at the book’s solution, consider the following:
• The constructor and methods used inside the method are part of the JSlider API
• Although not shown in the UML diagram, sliderMax and sliderMin are apparently variables in the ShowBallistics class
44
• The method wraps a call to construct a JSlider• The plan appears to be to wrap construction and
initialization of a slider appropriate to the application in a single method, rather than doing construction and initialization in straightline code (in the ShowBallistics constructor for example)
• If you study the code, you’ll realize that it has something in common with the singleton design pattern
• Among the things the method implements is lazy initialization
45
Solution 9.1, part 1• public JSlider slider()• {• if(slider == null)• {• slider = new JSlider();• sliderMax = slider.getMaximum();• sliderMin = slider.getMinimum();• slider.addChangeListener(this);• slider.setValue(slider.getMinimum());• }• return slider;• }
46
Solution 9.1, part 1, Discussion
• The only thing missing from the implementation of the slider() method was the parameter to the call to the method addChangeListener()
• The ShowBallistics class itself implements the interface ChangeListener
• Therefore, when constructing the slider, it is possible to add to it an instance of ShowBallistics, namely the ShowBallistics instance which constructs the slider itself
• This containing instance of ShowBallistics then serves as the listener for the JSlider that it constructs
47
Challenge 9.1, part 2, provided incomplete code for stateChanged()
• public void stateChanged(ChangeEvent e)• {• double val = slider.getValue();• double tp = (val – sliderMin) / (sliderMax – sliderMin);
• burnPanel(). ?? ( ?? );• thrustPanel(). ?? ( ?? );• valueLabel(). ?? ( ?? );• }
48
• Before looking at the book’s solution, consider the following:
• We haven’t been told exactly what the burnPanel(), thrustPanel(), and valueLabel() methods are for
• However, if the book follows the same plan for them as for slider(), it means that they wrap up the construction and initialization of objects for the use of the ShowBallistics class
• In other words, in the given code, the beginnings of the blank lines create anonymous instances of the panels and the label
• The rest of the lines make calls on those objects
49
• Each of the calls in the given code that need to be completed are of this form, for example:
• BallisticsPanel object.method(parameter)• The only method that is shown in the
BallisticsPanel is setTPeak(tPeak:double)• That suggests that that is the method called• The value of tPeak that is passed should have
something to do with the current value of the slider
50
Solution 9.1, part 2
• public void stateChanged(ChangeEvent e)• {• double val = slider.getValue();• double tp = (val – sliderMin) / (sliderMax – sliderMin);
• burnPanel().setTPeak(tp);• thrustPanel().setTPeak(tp);• valueLabel().setText(Format.formatToNPlaces(tp, 2));
• }
51
Solution 9.1, part 2, Discussion
• It turns out that the predictions about the solution were pretty accurate
• For the two panels, you call the setTPeak() method and you pass it the normalized value of tpeak, tp, which was calculated just above those calls
• The exact form of the call on valueLabel() couldn’t have been predicted
• However, a glance at the API for JLabel would have shown setText() as a likely candidate, and it is clear that the same value, tp, would be sent to it
52
A General Discussion of the First Design
• This is a narrative of how the parts of the first design are tied together
• The ShowBallistics class has all of the graphical components of the application inside itself
• The ShowBallistics class also implements the listener interface
• Therefore, when the ShowBallistics class creates the slider, it adds itself to the slider as the listener
53
• It is the stateChanged() method in the ShowBallistics class that is notified when the slider belonging to the class changes
• Because the ShowBallistics class has all of the graphical components in itself, that means that it has direct access to them
• In the implementation of stateChanged() the ShowBallistics class can make whatever calls are needed in order to update those components to reflect changes to the slider
54
• In favor of this design, you could observe that everything is wrapped up in a limited number of classes
• Making the class that contains the components a listener may be regarded as tricky, or it may be regarded as clever
• In any case, it means that there is just one listener for everything, which might also appear to be in the design’s favor
55
• Keep in mind that the authors of this book are merely showing a Java coding technique that differs from the technique adopted from Horstmann and Cornell for use in CS 202
• Consider the example from CS 202 shown in the UML diagram on the following overhead
56
57
• The MiscButtonPanel doesn’t implement the interface for a button listener
• Instead, it has an inner class which is a button listener
• This book’s design code has the panel implement a listener interface and then adds itself to the listener
58
• The end result for both coding techniques is approximately the same
• In this book’s code, the stateChanged() method is in the panel and has access to everything in the panel
• In the previous code, the actionPerformed() method was in an inner class, so it had access to everything in the panel
• Either way, these techniques might be good for simple situations, but the very thing that makes them easy in a simple case is a disadvantage in the long run
• All of the application’s contents can be mixed together in a single place, in this case a panel
59
The First Design Doesn’t Implement the Observer Design Pattern
• Recall the key element of the definition of the Observer design pattern
• “…when one object changes state, all its dependents are notified so that they can react to the change.”
• The object of interest here is the slider• The dependents are the burn panel, the thrust
panel, and the label
60
• This design does not notify each of those components individually
• The design notifies the ShowBallistics panel, which deals with each of the dependents with a separate line of code in the stateChanged() method
• Again, the claim is not made that this is bad, but in this sense it’s a monolithic design
61
• In theory, the book is introducing design patterns which lead to more understandable, flexible, maintainable code
• Presumably, the application of the Observer pattern to this application would be an improvement
• The book states that it would be possible to create a more fine-grained Observer by changing the application design so that each component registered itself to receive changes to the slider
62
• Challenge 9.2• Provide a new class diagram showing a design
that lets each interested object register for slider events. Be sure to account for the label that shows the slider’s value.
• Comment mode on:• As usual, it’s hard to predict from scratch what
the solution will be, but once you see it, you’ll find that what they did was straightforward
63
64
• The class ShowBallistics2 now has references to two instance variables, each of type BallisticsPanel2
• The two references correspond to the burn rate and thrust graphs
• The BallisticsPanel2 class is a subclass of JPanel
65
• The BallisticsPanel2 class implements the ChangeListener interface
• So the basic coding technique remains the same
• The panel for a graph implements the ChangeListener interface, not ShowBallistics2, the overall panel
66
• ShowBallistics2 also has a reference to an instance variable of type BallisticsLabel2
• BallisticsLabel2 is a subclass of JLabel• BallisticsLabel2 also implements the
ChangeListener interface
67
• So the transformation is complete• Each constituent graphical part of the
application implements the ChangeListener interface
• This means that each listens separately for changes in the slider
• When changes occur, the stateChanged() method is activated in each
68
• The changes in the code needed to support this refactoring are pretty straightforward
• The constructor for the BallisticsPanel2 class takes in a reference to the slider
• Then the BallisticsPanel2 object is added to the slider as a listener, just like in the previous version of the code this was done for the ShowBallisticsPanel
• See the code on the next overhead
69
• public BallisticsPanel2(BallisticsFunction func, JSlider slider)
• {• this.func = func;• this.slider = slider;• slider.addChangeListener(this);• }
70
• The stateChanged() method for the BallisticsPanel2 class is analogous to the stateChanged() method for the original ShowBallistics class
• This method gets the value of the slider• It gets the max and min values for the slider• It normalizes the value to the range from 0 to 1
and sets tPeak to this value• It then calls repaint()• See the code on the next overhead
71
• public void stateChanged(ChangeEvent e)• {• double val = slider.getValue();• double max = slider.getMaximum();• double min = slider.getMinimum();• tPeak = (val – min) / (max – min);• repaint();• }
72
Random questions not raised in the book
• Note that this isn’t threaded code• It is interesting to consider, with three different
objects listening for a change, which will be notified first?
• Is there some predefined order in which the code of the listeners will run?
• Does this depend on the order in which the BallisticsPanel2 and BallisticsLabel2 objects are constructed and put into the ShowBallistics2 class?
73
Points raised by the book which will lead to the next design step
• The book states that the refactoring so far is good in this sense:
• Each object is registered separately• That means that the distribution of
responsibility is good
74
• However, if you were to write the stateChanged() method for the BallisticsLabel2 class, it would be virtually the same as the stateChanged() method for the BallisticsPanel2 class
• Getting the value of the slider, normalizing it, etc. would all be the same
• It would be desirable to eliminate duplication like this from the code
75
• The book says that the way to do this is to abstract out another problem domain object as a separate class in the design
• This new class would be Tpeak, a container for the t peak value
• The application overall would listen to the slider and update the Tpeak object
• The other components would be registered to listen for changes to the Tpeak object
76
• According to the book, this change would result in a model-view-controller design
• Tpeak would be the model, the container for state
• The graphics panels which listen for changes in the Tpeak object would be the view
77
• The slider, which the overall application listens to, would be the controller
• The view and controller don’t interact directly with each other
• They interact solely by means of their listening and updating relationships with the model
78
The End?
• This is the break point that usually comes in the seventies in the numbering of the overheads
• Hopefully the end of the class period will not have been reached by this point
• The book next elaborates on the model-view-controller design pattern
• After that it talks about observability in Java• Hopefully there will be time to cover these topics in class• Otherwise, you’ll have to read about them on your own
and ask questions if you have them
79
Model/View/Controller
• One of the reasons for design patterns like MVC is simply to divide functionality into classes and packages small enough to maintain
• More important is that the division be done logically
• Listeners in Java make this possible, but with listeners it’s also possible make a monolithic design
80
• The view of an application corresponds to “look” and the control of an application corresponds to “feel”
• In theory it would be possible to separate the two, but in practice they are usually closely linked
• The fundamental effect of applying the MVC design pattern is to force the separation of the model from the graphical components
81
• I don’t care for the way the next part of the chapter is organized
• I also don’t care for some of the material covered
• These overheads are organized differently and the undesirable stuff is simply set off with a Skull and Crossbones notation
82
Skull and Crossbones Start Here.The book launches into a discussion that is not helpful starting here. It will be skipped in the presentation, although it’s included in case you read the
book and want to see how the overheads and the text relate.
• At this point the book mentions BurnRate and Thrust classes
• These haven’t been a part of the discussion or description of the application so far
• It seems to me that the authors are off the wall
• Unless these classes come up again, the mention of them here can simply be ignored
83
• Challenge 9.3• Create a class diagram that shows the
application depending on the slider and the text box and plotting panels depending on a Tpeak object
• Comment mode on:• I also think the authors are confused here• They refer to a text box, but I am pretty sure
that what they have in mind is the label
84
85
• Quite frankly, I think the previous diagram pushes the limits of the usefulness of UML
• It is hard to see the overall plan to the design• The book uses this as a take-off point for the
next iteration in redesign• I think it makes sense to look at the redesign
and hope it’s better than this one without worrying too much about how the shortcomings of this one lead to the next one
86
Skull and Crossbones End HereRational presentation of what’s going on starts
after this.
87
• The book now says that when you use the MVC design patterns, classes having to do with the view and controller go into an upper, GUI layer
• Classes having to do with the model go into a lower, business layer
• The upper layer depends on the lower layer• A UML of the current application using these
ideas is shown on the next overhead
88
89
• The critical things evident in the diagram are that there is a Tpeak class that is a subclass of the Observable class
• The methods in the Observable class will be of interest
• They are addObserver(), notifyObservers(), and setChanged()
90
• Also, the classes BallisticsPanel and BallisticsLabel both implement the Observer interface
• Finally, notice the dashed lines with open arrowheads linking the panels and label to Tpeak
• This UML symbol means “has or makes use of” but indicates that the Tpeak object is not an instance variable of the objects that have or make use of it
• One of the relationships is singled out in the UML diagram on the next overhead
91
92
• The critical thing to notice here is that a class that implements the Observer interface has to implement the update() method
• The update() method takes a parameter that is of type Observable object
93
• Now for some of the code elements of the ShowBallistics application redesigned using the MVC design pattern
• The model could be contained in a Tpeak class• Keep in mind that the current redesign is based on the
idea that you don’t observe the slider, a graphical object• Instead, you observe t peak, one of the elements of the
business model• Code for a generic version of an observable Tpeak class
is shown on the next overhead
94
• import java.util.Observable;• public class Tpeak extends Observable• {• protected double value;• public Tpeak(double value)• {• this.value = value;• }
95
• public double getValue()• {• return value;• }• public void setValue(double value)• {• this.value = value;• setChanged();• notifyObservers();• }• }
96
• The book observes that this code is highly generic and not really specific to the t peak value
• On the other hand, it illustrates very simply and concretely one part of the syntax for observability
• At some other place in the code, the thrust and burn time panels and the label would be registered to listen for changes in a Tpeak object
• (Obviously, that code hasn’t been shown yet. Stay tuned.)
97
• The change in the Tpeak object occurs when its setValue() method is called
• Within that method, the change is made• Then the setChanged() method is called on the
implicit parameter• No implementation of setChanged() is shown,
so this is a call to the version inherited from the superclass Observable
98
• Following the call to setChanged() there is a call to notifyObservers()
• This is also an inherited method• It is necessary to call setChanged() before
calling notifyObservers()• Once again, we’re relying on Java magic• The effect of the call to notifyObservers() will
be explained next
99
• The relationship between the notifyObservers() method in an Observable object and the update() method in an Observer object is that of a callback sequence
• notifyObservers() calls the update() method of all objects that have been registered as observers of the object on which notifyObservers() is called
100
• Next the book is going to pursue the BallisticsLabel class as a specific example of an observer in this new design
• Two UML diagrams for the latest version of the application are shown on the following overheads
101
102
103
• Regarding BallisticsLabel, keep in mind that the dashed line with open arrow says that it can use an object of the Tpeak class without keeping a reference to it as an instance variable
• The constructor for BallisticsLabel takes a reference to a Tpeak object as its parameter
• In the constructor the BallisticsLabel can register to be notified of updates on the Tpeak object
104
• The BallisticsLabel class has to implement the update() method
• The update() method takes two parameters• Once BallisticsLabel is registered, when updates
occur to the “interesting object” (Tpeak) update() is called
• The parameter typed Observable is a superclass reference to the Tpeak object that the BallisticsLabel object is registered on
105
• The existence of this parameter when update() is called explains why BallisticsLabel doesn’t have to retain a reference to the “interesting object”
• Because Tpeak is a subclass of Observable, inside update() the Observable parameter can be cast to Tpeak and any information needed about it can be acquired through method calls
106
• The book adds that the update() method can extract the new value of Tpeak
• It can change the label’s text to agree with that
• And then it can repaint• Even though this seems like precious little to
go on, the book now gives the next challenge
107
• Challenge 9.4• Write the complete code for
BallisticsLabel.java.
108
• Comment mode on:• Presumably the book did give a fairly complete
idea of what the constructor and the update() method should contain
• Additional information could be gained by looking up the Observer interface and Observable class in the Java API
• As usual, the simplest approach is just to look at what the book did
109
• import javax.swing.*;• import java.util.*;• public class BallisticsLabel extends JLabel implements
Observer• {• public BallisticsLabel (Tpeak tPeak)• {• tPeak.addObserver(this);• }• public void update(Observable o, Object arg)• {• setText(“” + ((Tpeak) o).getValue());• repaint();• }• }
110
• In summary, the code discussed so far accomplished the following
• 1. Subclasses of Observable have to notify registered dependents (observers) of changes
• Since Tpeak is observable, it has a setValue() method that calls setChanged() and notifyObservers()
111
• 2. Implementations of observer have to register their interest and update themselves appropriately
• This means, for example, that the BallisticsLabel class takes an instance of Tpeak as a construction parameter and calls addObserver on it, sending this as the parameter
• Then the update() method of BallisticsLabel has to obtain the value of the observed object, set its own characteristics accordingly, and then call repaint() on itself
112
• There may now be some use in looking at the overall UML diagram of the application that was skipped in the Skull and Crossbones section earlier
• Look carefully at the bottom half of the following UML diagram
• It contains the elements described so far
113
114
• Now look also at the top half of the foregoing UML diagram
• The overall application is ShowBallistics3• Arrows coming from its left bottom show that
instances of BallisticsPanel, BalllisticsLabel, and Tpeak belong to it
• That’s where those components fit into the big picture
115
• An arrow coming from the right of ShowBallistics3 shows that an instance of JSlider also belongs to it
• The slider has a ChangeListener• The ChangeListener sets the value of Tpeak• This is the third, and last piece of the puzzle
116
• Beginning from the beginning, from controller (user action), to model, to view
• 1. Changes in the slider (controller) have to update the interesting object, an instance of Tpeak
• 2. The instance of Tpeak (model) has to extend Observable so that observers can be notified
• 3. The instances of BallisticsPanel and BallisticsLabel (view) have to implement Observer so that they can be updated
117
• So, to provide the last piece of the puzzle, it’s necessary to consider the implementation of the slider
• Recall that construction of the slider is packaged up in this method in the ShowBallistics3 class:
• public class JSlider slider()
118
• The book takes up this implementation now• It points out that it will implement the
ChangeListener belonging to the slider as an anonymous (inner) class
• You may recall that this syntax was mentioned in CS 202 (and eschewed)
• This book uses this syntax, so at the very least it’s necessary to understand it
119
• Challenge 9.5• Suppose that tPeak is an instance of Tpeak and
an attribute of the ShowBallistics3 class. Complete the code for ShowBallistics3.slider() so that the slider’s changes update tPeak:
120
• Comment mode on:• Keep in mind that the t peak object and the
slider object are both instance variables in ShowBalllistics3
• This means that code for the slider will have access to the variable t peak
121
• A more detailed statement of the challenge is this
• Implement the changeListener() method for the slider
• In other words, when the user moves the slider, what should happen in the code?
• The incomplete code for this challenge is shown on the next overhead
122
• public JSlider slider()• {• if(slider == null)• {• slider = new JSlider();• sliderMax = slider.getMaximum();• sliderMin = slider.getMinimum();• slider.addChangeListener• (• new ChangeListener()• {• // Challenge!• }• );• slider.setValue(slider.getMinimum());• }• return slider;• }
123
• Solution 9.5• One solution is: [See the multiple lines of
code/single Java statement containing the anonymous ChangeListener on the next overhead. The rest of the slider() code is not repeated.]
124
• slider.addChangeListener(new ChangeListener()
• {• public void stateChanged(ChangeEvent e)• {• if(sliderMax == sliderMin) return;• tPeak.setValue(• (slider.getValue() – sliderMin)• / (sliderMax – sliderMin));• }• });
125
• In summary, this is what happens in the stateChanged() method
• The value of t peak is normalized between 0 and 1 according to the position of the (new) position of the slider
• The value of the t peak object is updated to this new value
126
• The book points out that the flow of events in an application like this may seem indirect
• The progression is slider to change listener to interesting object (instance of Tpeak)
• This is followed by notification of the panels and the label
• Change propagates from the upper, GUI, layer to the lower, business, layer and back again
127
• Challenge 9.6• Fill in the messages in Figure 9.5.
128
129
• Solution 9.6• Figure B.9 shows the calls that flow when a
user moves the slider in the ballistics application
130
131
• This ends the book discussion of the ShowBallistics3 design
• The book states that the key feature of the implementation of the Observer/MVC design is the layering that results
• This layering is an apportioning of responsibility• The business layer takes care of the model• The GUI layer takes care of the control and view
132
• This makes it possible to add a new GUI without changing the model
• The book suggests adding a GUI for a handheld device, for example
• It also makes it possible to make changes at the business level
133
• A new controller in the GUI layer might be hooked in to change the value of Tpeak
• If so, the changes will automatically propagate to the view
• It will not be necessary to recode the viewing mechanism
134
• A layered design supports implementation in a physically layered environment, like client-server
• Now the software layering means changes in client software don’t affect server software and vice-versa
• In summary, the Observer design pattern and the Observer machinery in Java support the MVC design pattern
• The grand conclusion is that the MVC design pattern is the recognized gold standard for complex GUI applications
135
The End?
• It is clear that it will not be possible to cover anything else in the chapter during lecture
• I probably won’t even get this far• As a result, you are not responsible for the
remainder of the chapter• The remaining diagrams of the chapter have
been tipped in below, but you can ignore them
136
• If you want to read the rest of the chapter, be my guest
• It covers the PropertyChangeSupport class in Java
• This is useful in cases where you would like to extend Observable, but you can’t…
137
138
139
140
The End