1.4k likes | 1.56k Views
Unit 30 Observer. Summary prepared by Kirk Scott. Design Patterns in Java Chapter 9 Observer. Summary prepared by Kirk Scott. The Introduction Before the Introduction. The book’s logic of organizing patterns by intent puts the Observer pattern relatively early
E N D
Unit 30Observer Summary prepared by Kirk Scott
Design Patterns in JavaChapter 9Observer Summary prepared by Kirk Scott
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
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
Think back to Wari and TogizKumalak • 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
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
Taking TogizKumalak 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
The logic of the Model-View-Controller pattern is to cleanly separate these functionalities into different classes • Although there was some separation in TogizKumalak, 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
In TogizKumalak 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
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 TogizKumalak
At the second stage of the development of TogizKumalak, 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
At the third stage of development of TogizKumalak (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
Stated simplistically • At stage 2, TogizKumalak was 50% system supplied magic, based on the callback sequence • At stage 3, TogizKumalak 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
So, the final version of TogizKumalak 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 TogizKumalak • 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
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
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
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
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
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
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
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
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.
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
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 TogizKumalak • This makes the book example good for illustrating the pattern, but TogizKumalak 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
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
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
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
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
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
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
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
On the right hand side is the BallisticsPanel class • It is a subclass of the JPanel class • It makes use of the BallisticsFunction interface
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
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
The ShowBallistics class contains four methods • burnPanel() returns a reference to an instance of BallisticsPanel • thrustPanel() returns a reference to an instance of BallisticsPanel
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
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
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
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; • }
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
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
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; • }
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
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(). ?? ( ?? ); • }
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
Each of the calls in the given code that need to be completed are of this form, for example: • BallisticsPanelobject.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
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)); • }