chapter 9 observer

210
Chapter 9 Observer Summary prepared by Kirk Scott 1

Upload: mikaia

Post on 24-Feb-2016

32 views

Category:

Documents


0 download

DESCRIPTION

Chapter 9 Observer. Summary prepared by Kirk Scott. Design Patterns in Java Chapter 9 Observer. Summary prepared by Kirk Scott. The Introduction Before the Introduction. Think back to Wari and Togiz Kumalak The very first implementations weren’t graphical at all - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Chapter 9 Observer

1

Chapter 9Observer

Summary prepared by Kirk Scott

Page 2: Chapter 9 Observer

2

Page 3: Chapter 9 Observer

3

Page 4: Chapter 9 Observer

4

Page 5: Chapter 9 Observer

5

Page 6: Chapter 9 Observer

6

Page 7: Chapter 9 Observer

7

Page 8: Chapter 9 Observer

8

Page 9: Chapter 9 Observer

9

Design Patterns in JavaChapter 9Observer

Summary prepared by Kirk Scott

Page 10: Chapter 9 Observer

10

The Introduction Before the Introduction

• 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

Page 11: Chapter 9 Observer

11

• 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

• Input might consist of various objects with listeners attached

• Output might consist of various panels and their contents

Page 12: Chapter 9 Observer

12

• There were also parts of the design where the state of the board and the logic of play were implemented

• But this could have been in a higher level class that extended JPanel, for example

• In other words, even though the various elements of model, view, and controller were becoming obvious, in the overall design there was no clear distinction about how and where those things should be implemented

Page 13: Chapter 9 Observer

13

• Taking Wari as an example, this is the Model-View-Controller idea:

• The model part would be the board, the rules of play, and the state of the game

• The view part would be the output side of the application

• The controller part would be the input side of the application

Page 14: Chapter 9 Observer

14

• The logic of the Model-View-Controller pattern is to cleanly separate these functionalities into different classes

• Although there was some separation in the Wari examples, they didn’t have a pure model-view-controller design

Page 15: Chapter 9 Observer

15

• At the second stage of the development of Wari, 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

Page 16: Chapter 9 Observer

16

• 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

Page 17: Chapter 9 Observer

17

• At the third stage of development of Togiz Kumalak (the final project for CSCE 202), 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

Page 18: Chapter 9 Observer

18

• This made life considerably easier because whenever the state changed, there was no need to call repaint()

• The system took care of this automatically

Page 19: Chapter 9 Observer

19

• 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

Page 20: Chapter 9 Observer

20

• If you got the final project to work, then empirically its design was OK

• But you basically flailed your way towards a nice implementation, trying to follow examples without necessarily having a good conceptual grasp of what you were doing

Page 21: Chapter 9 Observer

21

Where We’re Headed

• In Wari, 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 detect and react to events• It turns out that you can also have observers,

which can be notified of changes in the state of objects

Page 22: Chapter 9 Observer

22

• Having listeners on the input side and observers on the output side allows for complete separation of the different parts of a design

• 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

Page 23: Chapter 9 Observer

23

• Java contains an interface named Observer and a class named Observable

• These are the constructs which support observability

Page 24: Chapter 9 Observer

24

What the Book Covers

• The book develops a sequence of examples based on Oozinoz

• As usual, I’m not interested in the physics content of their code

• The examples will illustrate Observer and Model-View-Controller concepts, and how observability is made available in the Java API

Page 25: Chapter 9 Observer

25

• 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

Page 26: Chapter 9 Observer

26

• 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 paradigms for how this might be accomplished in code

Page 27: Chapter 9 Observer

27

• 1. The clients have to regularly check the interesting object for changes

• 2. The interesting object notifies clients of changes in its state

• When it makes the notification it somehow automatically updates the client based on the changes that have occurred

• This would be the most general paradigm

Page 28: Chapter 9 Observer

28

• 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

Page 29: Chapter 9 Observer

29

• The use of listeners as seen so far is representative of the third approach

• User actions like clicking the mouse are events• When an event occurs, code is “notified”

when the system calls a listener and passes it the event

Page 30: Chapter 9 Observer

30

• 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 then take certain actions if desired

Page 31: Chapter 9 Observer

31

Observers and Multicasting

• Multicasting came up at the end of CSCE 202• 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

Page 32: Chapter 9 Observer

32

• Up to that point, the plan had appeared to be one actionone listener

• Then it became one actionmany listeners• Using the observer terminology of the book,

the situation became one interesting objectmany clients

Page 33: Chapter 9 Observer

33

• 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

Page 34: Chapter 9 Observer

34

Book Definition of the Pattern

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

Page 35: Chapter 9 Observer

35

Comment Mode On

• Consider a general statement like this:• Good code localizes responsibility so that

objects are not dependent on each other• The reality is, that at a cosmic level, when

designing and developing a system, by definition you’re creating a set of classes and runtime objects that depend on each other from a problem domain point of view

Page 36: Chapter 9 Observer

36

• An application which contains state, has a graphical user interface, and is event driven, necessarily has classes that depend on each other

• The observer and MVC design patterns are not about the problem domain

• They have been developed as general templates for managing the kinds of dependencies that exist in all kinds of software that GUI’s

Page 37: Chapter 9 Observer

37

A Classic Example: Observer in GUIs

• Listeners are the classic example of dependent clients that are notified when an event occurs

• It will turn out that observing is analogous to listening

• The book is going to develop an example which uses a slider control

• The slider is a classic user interface component with a listener

Page 38: Chapter 9 Observer

38

• The listener responds to events and changes application state

• When state changes, an observer can be notified

• The observer can take various actions, including changing the view of the application as a result of the change in the state

Page 39: Chapter 9 Observer

39

• This division of labor is the break with your previous experience in creating graphical apps

• In your previous efforts, it was highly likely that the listener did two things:

• It changed the state and it also updated the graphical view (through repainting, etc.)

• Now changes to state and changes to the view will be apportioned to listeners and observers, respectively

Page 40: Chapter 9 Observer

40

Getting Started with the Book’s Example

• See the following overhead• The slider is at the bottom• To its left is a label which shows the current

value associated with the slider’s position• Above it there are two panels which depend

on changes to the slider’s value/position

Page 41: Chapter 9 Observer

41

Page 42: Chapter 9 Observer

42

• As will be the case with other examples, the book gives a description of the application domain physics involved in this example

• The physics is of no particular interest to us• But we need to understand enough in order to

be able to follow the discussion of how the components of the application interact

Page 43: Chapter 9 Observer

43

• 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

• 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• tpeak represents that point in time in the range from 0

to 1 where the burn rate is at a maximum

Page 44: Chapter 9 Observer

44

• Here are the book’s equations for burn rate and thrust

• Burn rate is a function of time• Thrust is a function of the burn rate

Page 45: Chapter 9 Observer

45

• Controller: The slider in the application allows the user to visually change the value of tpeak, which is part of the state of the application

• Model: tpeak is used in the equations for the burn rate and thrust curves

• View: Whenever a change is made in tpeak, the panels containing the graphs for burn rate and thrust have to be updated

Page 46: Chapter 9 Observer

46

• Observe that by definition, the burn rate graph has a maximum at tpeak

• I’m not interested enough in the physics to reason why, but the formula for thrust, mathematically speaking, also gives 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

Page 47: Chapter 9 Observer

47

• The folder for this unit includes some example code from the authors

• 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

Page 48: Chapter 9 Observer

48

• The maximums of the two curves merely move to the new position specified by the slider

• When you see this, it becomes apparent that you could probably get the same visual behavior through mindless trickery, shifting things from left to right

• But the point is to understand how they’re using the pattern, so we will follow through with the mechanics of the example as given

Page 49: Chapter 9 Observer

49

The First Example

• 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

Page 50: Chapter 9 Observer

50

Page 51: Chapter 9 Observer

51

• 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

Page 52: Chapter 9 Observer

52

• On the right hand side is the BallisticsPanel class

• It is a subclass of the JPanel class• It makes use of the BallisticsFunction interface

Page 53: Chapter 9 Observer

53

• 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

Page 54: Chapter 9 Observer

54

• The ShowBallistics class is the heart of this design

• The ShowBalllistics class contains two instances of the BallisticsPanel class

• There is one panel each for the burn rate and the thrust graphs

Page 55: Chapter 9 Observer

55

• The ShowBallistics class contains four methods• burnPanel() returns a reference to an instance

of BallisticsPanel• thrustPanel() returns a reference to an

instance of BallisticsPanel

Page 56: Chapter 9 Observer

56

• 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

Page 57: Chapter 9 Observer

57

• 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

Page 58: Chapter 9 Observer

58

• There are not many things in the ShowBallistics class and in principle, it seems easy enough to understand what they all are On the other hand, the things range from view, to controller, to model

• It is the fact that all of these things are together in one class (kind of like the integrated Wari applications) that will eventually be identified as a conceptual shortcoming in the design

Page 59: Chapter 9 Observer

59

Code Challenges (Version 1 of the Example)

• On the following overheads the given blocks of incomplete code will be shown, 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

Page 60: Chapter 9 Observer

60

• The UML diagram is repeated again on the following overhead for reference

• The UML should serve as sort of a road map to the things the book wants to implement

Page 61: Chapter 9 Observer

61

Page 62: Chapter 9 Observer

62

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.

Page 63: Chapter 9 Observer

63

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

Page 64: Chapter 9 Observer

64

• Before looking at the book’s solution, consider the following:

• This method is called by client code to obtain the slider in the application

• The method contains a call to a constructor• Lazy construction is done• This is singleton-like

Page 65: Chapter 9 Observer

65

• Whether something is a singleton or not, in various places the book will implement methods like this

• Construction and initialization of a slider appropriate to the application are wrapped in a single method, rather than doing construction followed by initialization in client code

Page 66: Chapter 9 Observer

66

• The constructor and methods used inside the method are part of the JSlider API in Java

• Although not shown in the UML diagram or the code as given so far, sliderMax and sliderMin are apparently variables in the ShowBallistics class

Page 67: Chapter 9 Observer

67

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

Page 68: Chapter 9 Observer

68

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, which is the class which contains the slider() method implements the ChangeListener interface

• It contains a stateChanged() method

Page 69: Chapter 9 Observer

69

• Therefore, when constructing the slider, it is possible to add to it an instance of ShowBallistics as the slider’s listener

• The underlying assumption is that the slider belongs to a ShowBallistics object

• That object calls the slider() method to obtain the slider

• Therefore, “this”, the ShowBallistics object, is the correct parameter for the slider’s listener

Page 70: Chapter 9 Observer

70

• So the containing instance of ShowBallistics serves as the listener for the JSlider that it obtains

• The mechanics of adding the change listener is a relatively small detail

• In several different design patterns we will see “this” being sent as a parameter

• Overall, the ChangeListener interface and the implementation of the stateChanged() method will be of greater interest

Page 71: Chapter 9 Observer

71

Challenge 9.1, part 2

• Complete the code for the stateChanged() method

• The UML diagram is repeated on the following overhead for reference

• This will be followed by part 2 of the challenge

Page 72: Chapter 9 Observer

72

Page 73: Chapter 9 Observer

73

Provided incomplete code for stateChanged()

• public void stateChanged(ChangeEvent e)• {• double val = slider.getValue();• double tp = (val – sliderMin) / (sliderMax – sliderMin);

• burnPanel(). ?? ( ?? );• thrustPanel(). ?? ( ?? );• valueLabel(). ?? ( ?? );• }

Page 74: Chapter 9 Observer

74

• Comment mode on:• 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

Page 75: Chapter 9 Observer

75

• 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 endings of the lines make calls on those objects

Page 76: Chapter 9 Observer

76

• 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

Page 77: Chapter 9 Observer

77

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

• }

Page 78: Chapter 9 Observer

78

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

Page 79: Chapter 9 Observer

79

• 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

Page 80: Chapter 9 Observer

80

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

Page 81: Chapter 9 Observer

81

• 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 the method 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

Page 82: Chapter 9 Observer

82

• 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

Page 83: Chapter 9 Observer

83

• 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 CSCE 202

• Consider the example from CSCE 202 shown in the UML diagram on the following overhead

Page 84: Chapter 9 Observer

84

Page 85: Chapter 9 Observer

85

• The MiscButtonPanel doesn’t implement the interface for a button listener

• Instead, it has an inner class which is a button listener

• The end result for both coding techniques is approximately the same

Page 86: Chapter 9 Observer

86

• In this book’s code, the stateChanged() method is in the ShowBallistics class

• The ballistics class has the panels• So the stateChanged() method has access to

the panels• In the CSCE 202 code, the actionPerformed()

method was in an inner class of the panel, so it had access to everything in the panel

Page 87: Chapter 9 Observer

87

• 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

• The are monolithic designs• All of the application’s contents are mixed

together in a single place• There isn’t a clean division between model, view,

and controller

Page 88: Chapter 9 Observer

88

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 is really the value of tpeak, but in this integrated design, the current value of the slider plays that role

• The dependents are the burn panel, the thrust panel, and the label

Page 89: Chapter 9 Observer

89

• This design does not notify each of those components individually

• The design notifies the ShowBallistics object, which deals with each of the dependents with a separate line of code in the stateChanged() method

• The design works• But the goal will eventually be to see how to

make a better design by applying the pattern

Page 90: Chapter 9 Observer

90

• Again, a comparison can be made with design choices from CSCE 202

• You can create a “clear” button which has the purpose of zeroing out the contents of multiple text fields

• You could potentially have just one listener• That listener could contain a line of code for

each text field, zeroing it out

Page 91: Chapter 9 Observer

91

• Or, each text field could have its own listener• The listener would contain just one line of

code, zeroing out the text field it belonged to• Then these many listeners would all be added

to the one clear button• This was how the multi-casting example

worked

Page 92: Chapter 9 Observer

92

• Depending on the situation, either solution may be desirable

• (In Android coding, it can be convenient to have a single listener containing multiple lines of code for different cases or objects)

• We want to see how these ideas are applied using the observer design pattern

Page 93: Chapter 9 Observer

93

Modifying the Design

• In theory, the book is introducing design patterns which lead to more understandable, flexible, maintainable code

• Presumably, the use of the Observer pattern in this application would be an improvement

• The book states that it would be possible to create a more fine-grained design by changing the application so that each component registered itself to receive changes to the slider

Page 94: Chapter 9 Observer

94

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

Page 95: Chapter 9 Observer

95

• 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

• The old diagram is shown for reference on the following overhead

• The new diagram is shown on the overhead after that one

Page 96: Chapter 9 Observer

96

Page 97: Chapter 9 Observer

97

Page 98: Chapter 9 Observer

98

• Overall, the new ShowBallistics2 class has references to three instance variables

• It has references to two instance variables, each of type BallisticsPanel2

• The BallisticsPanel2 class is a subclass of JPanel• The two references correspond to the panels

containing the graphs of the burn rate and thrust

Page 99: Chapter 9 Observer

99

• The BallisticsPanel2 class implements the ChangeListener interface

• In the previous design, the ShowBallistics class contained the panels and implemented the ChangeListener interface

• In this design, the panels for the graphs, not ShowBallistics2, implement the ChangeListener interface

Page 100: Chapter 9 Observer

100

• ShowBallistics2 also has a third reference, to an instance variable of type BallisticsLabel2

• BallisticsLabel2 is a subclass of JLabel• Like the panels, BallisticsLabel2 also

implements the ChangeListener interface

Page 101: Chapter 9 Observer

101

• So the transformation requested in the challenge 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 in the slider occur, the stateChanged() method is called on the respective graphical objects, panels and label

Page 102: Chapter 9 Observer

102

This is Still Not an Example of Observer

• This result is still pretty analogous to what was done by the end of CSCE 202

• In CSCE 202, panels had listeners as inner classes

• Here, the panels themselves implement the ChangeListener interface

• This example expands this out to include the label

Page 103: Chapter 9 Observer

103

• The general idea is that each graphical element has listening capabilities associated with it

• This is a step in the right direction• But when you look at the UML diagram, you still

have to ask yourself, which parts of the diagram constitute the model, view, and controller

• In particular, where is the model (T peak)?

Page 104: Chapter 9 Observer

104

Code for the New Design

• The changes in the code needed to support this refactoring are pretty straightforward

• The BallisticsPanel2 class is the class that represents the burn rate and thrust graphs

• It will have a constructor• The constructor for the BallisticsPanel2 class

will take in a reference to the slider that it is a listener for

Page 105: Chapter 9 Observer

105

• Then the BallisticsPanel2 object is added to the slider as a listener

• The parameter is “this” because the reference to the slider is contained by the panel, which implements listening capabilities

• The code for the constructor is given on the next overhead

• The constructor also takes a function as a parameter, but for the time being we’re not interested in this implementation detail

Page 106: Chapter 9 Observer

106

• public BallisticsPanel2(BallisticsFunction func, JSlider slider)

• {• this.func = func;• this.slider = slider;• slider.addChangeListener(this);• }

Page 107: Chapter 9 Observer

107

• 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

Page 108: Chapter 9 Observer

108

• This implementation of the method then calls repaint()

• The need for the call to repaint() should be reminiscent of actionPerformed() methods for listeners belonging to panels in CSCE 202

• Obviously, the ultimate effect of calling repaint() depends on paintComponent(), but at the moment, the details of how a function is turned into a graph are not of interest

Page 109: Chapter 9 Observer

109

• Incidentally, the version of stateChanged() in the previous design did not show calls to repaint()

• It did contain calls to setTPeak() on the panels• Somewhere within that code painting would

have been triggered• In this version, the value of tPeak is set directly,

and the call to repaint() follows this• See the code on the next overhead

Page 110: Chapter 9 Observer

110

• public void stateChanged(ChangeEvent e)• {• double val = slider.getValue();• double max = slider.getMaximum();• double min = slider.getMinimum();• tPeak = (val – min) / (max – min);• repaint();• }

Page 111: Chapter 9 Observer

111

How This Works

• Recall that the application relies on the function class, so the details of how it works are not transparent

• However, the details are not important to the overall solution

• The point is that moving the slider causes the listener method, stateChanged(), to be called on each of the panels and on the label

Page 112: Chapter 9 Observer

112

• The stateChanged() method causes the relevant instance variables of the panels and label to be changed

• This is a change of state (model)• As before, in this example, this is Tpeak• When the state changes, the call to repaint()

causes the visual representation to be updated to reflect that fact

Page 113: Chapter 9 Observer

113

A Random question not raised by the book

• With three different objects listening for a change, which will be notified first?

• (Note that this isn’t threaded code)• Is there some predefined order in which the

code of the listeners will run?• This probably depends on the order in which the

BallisticsPanel2 and BallisticsLabel2 objects are constructed and added to the slider as listeners

Page 114: Chapter 9 Observer

114

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• In other words, they’re making the argument

that a single listener that affects many different things is probably not the best design choice

Page 115: Chapter 9 Observer

115

• You have two panels• You just have to write one implementation of

stateChanged() for the panel class• The same method applies generically to any

instance of that class• That method is relatively short and sweet

Page 116: Chapter 9 Observer

116

• 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

Page 117: Chapter 9 Observer

117

How to Take the Next Step

• The book says that the way to eliminate duplication 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 (observe) the Tpeak object

Page 118: Chapter 9 Observer

118

• This change would result in a full model-view-controller design

• Tpeak would be the model, the container for state

• The other variables we’ve been messing with in the stateChanged() method, the current value and the max and min of the slider were related to tpeak anyway

Page 119: Chapter 9 Observer

119

• The slider, which the overall application listens to, would be the controller

• The graphics panels and the label panel which observe changes in the Tpeak object would be the view

Page 120: Chapter 9 Observer

120

• The view and controller don’t interact directly with each other

• They interact solely by means of their relationships with the model

• The model is updated by listening for changes in the controller

• The view is updated by observing changes in the model

Page 121: Chapter 9 Observer

121

Model-View-Controller and Observability

• The book’s presentation of some of this seems to assume that the reader already knows about the Observer interface and the Observable class in the Java API

• This presentation will not exactly match the book’s

• Some detailed information about observation in the Java API will be given and then the example will be pursued further

Page 122: Chapter 9 Observer

122

The Motivation for the MVC Pattern

• When developing applications, classes need to remain relatively small and cohesive

• This goes all the way back to the idea of responsibility

• Classes should be self-contained—responsible for themselves

• Plus, they should be unitary—consisting of one thing, not many things

Page 123: Chapter 9 Observer

123

• This logic applies to graphical applications• The model contains the state of the

application• For most applications, it should be possible to

implement this as a single class• An instance of it will be an object of interest

Page 124: Chapter 9 Observer

124

• The view is the visual appearance of the application

• This corresponds to the “look” from the look and feel perspective

• When a change occurs in the model, that part of the application responsible for the view should be notified so that its visual appearance changes correspondingly

Page 125: Chapter 9 Observer

125

• The controller is that part of the application that is responsive to events

• This corresponds to the “feel” from the look and feel perspective

• Events trigger controller listeners• The code for the listeners causes changes in the

model• Ultimately, those changes should lead to changes

in the view

Page 126: Chapter 9 Observer

126

• As the foregoing examples illustrated, when using Java Swing, it’s possible to combine parts of the model, view, and controller into the same class

• The goal of the next example will be to completely move the model into its own class, Tpeak, and have clearly identifiable, and separate, view and controller classes

Page 127: Chapter 9 Observer

127

Java Machinery for Supporting MVC

• The Java API contains a class named Observable• The class in an application that contains the

model can extend Observable and inherit or override a few critical methods

• Methods exist in the API so that notifications of changes in the observable class can be sent to objects/methods interested in such changes

Page 128: Chapter 9 Observer

128

• The Java API also contains an interface named Observer

• The class in an application that implements Observer is effectively a listener

• An object of such a class can call methods requesting to be notified of changes in the observable class object

Page 129: Chapter 9 Observer

129

The Observable Class

• What follows is information from the Java API on the Observable class

Page 130: Chapter 9 Observer

130

• java.util • Class Observable

• java.lang.Object – java.util.Observable

• public class Observable extends Object

Page 131: Chapter 9 Observer

131

• This class represents an observable object, or "data" in the model-view paradigm.

• It can be subclassed to represent an object that the application wants to have observed.

Page 132: Chapter 9 Observer

132

• An observable object can have one or more observers.

• An observer may be any object that implements interface Observer.

• After an observable instance changes, an application calling the Observable's notifyObservers method causes all of its observers to be notified of the change by a call to their update method.

Page 133: Chapter 9 Observer

133

• The order in which notifications will be delivered is unspecified.

• The default implementation provided in the Observable class will notify Observers in the order in which they registered interest, but subclasses may change this order, use no guaranteed order, deliver notifications on separate threads, or may guarantee that their subclass follows this order, as they choose.

Page 134: Chapter 9 Observer

134

• Note that this notification mechanism has nothing to do with threads and is completely separate from the wait and notify mechanism of class Object.

• When an observable object is newly created, its set of observers is empty.

Page 136: Chapter 9 Observer

136

[In the list of methods, notice the italicized ones, emphasized with ***. They show up in the coming example.]

• Constructor Summary • Observable()

Construct an Observable with zero Observers.

• Method Summary

• *** void addObserver(Observer o) Adds an observer to the set of observers for this object, provided that it is not the same as some observer already in the set.

Page 137: Chapter 9 Observer

137

• protected void clearChanged() Indicates that this object has no longer changed, or that it has already notified all of its observers of its most recent change, so that the hasChanged method will now return false.

• int countObservers() Returns the number of observers of this Observable object.

Page 138: Chapter 9 Observer

138

• void deleteObserver(Observer o) Deletes an observer from the set of observers of this object.

• void deleteObservers() Clears the observer list so that this object no longer has any observers.

• boolean hasChanged() Tests if this object has changed.

Page 139: Chapter 9 Observer

139

• *** void notifyObservers() If this object has changed, as indicated by the hasChanged method, then notify all of its observers and then call the clearChanged method to indicate that this object has no longer changed.

Page 140: Chapter 9 Observer

140

• void notifyObservers(Object arg) If this object has changed, as indicated by the hasChanged method, then notify all of its observers and then call the clearChanged method to indicate that this object has no longer changed. protected

• *** void setChanged() Marks this Observable object as having been changed; the hasChanged method will now return true.

Page 141: Chapter 9 Observer

141

The Observer Interface

• java.util Interface Observer

• public interface Observer • A class can implement the Observer interface

when it wants to be informed of changes in observable objects.

• Since: JDK1.0 • See Also:Observable

Page 143: Chapter 9 Observer

143

[update() is the only method. Keep it in mind for the example to come.]

• Method Detail • update• void update(Observable o, Object arg) • This method is called whenever the observed

object is changed.

Page 144: Chapter 9 Observer

144

• An application calls an Observable object's notifyObservers method to have all the object's observers notified of the change.

• Parameters:• o - the observable object.• arg - an argument passed to the

notifyObservers method.

Page 145: Chapter 9 Observer

145

Continuing the Book’s Example

• The overall structure of the redesigned application will be considered next

• The redesign makes use of the observer mechanism

Page 146: Chapter 9 Observer

146

• 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:• The challenge refers to a text box, but in the

diagram you’ll see that what they have in mind is the label

Page 147: Chapter 9 Observer

147

Page 148: Chapter 9 Observer

148

• Comment mode on:• This UML diagram is laughably unbeautiful• It violates “Scott’s Principle” that it should be

possible to arrange the contents of a UML diagram in a logical way, whether symmetrical, hierarchical, etc., and that the visual presentation makes clear the logical relationship of the components of a diagram…

Page 149: Chapter 9 Observer

149

• In any case, the diagram does illustrate something important

• Notice that the arcs in the diagram are all open arrowheads

• Even though it’s a static structure diagram, it’s all about references (dependency) of one object to another at run time

Page 150: Chapter 9 Observer

150

• Four of the arcs are labeled, telling you the message passed between the objects (in other words, an action taken, a method called)

• These objects and actions break the design down into three parts, M, V, and C

• It might be better if the diagram somehow indicated observer/observability explicitly

• Future static structure diagrams will show this

Page 151: Chapter 9 Observer

151

• Notice this set of relationships:• JSliderstateChangedChangeListenersetVal

ueTpeak• The JSlider with its listener is the controller• Tpeak is the model, which has its state

changed by actions of the controller

Page 152: Chapter 9 Observer

152

• Now consider these relationships:• TpeakupdateBallisticsPanel• TpeakupdateBallisticsLabel• The BallisticsPanel and BallisticsLabel are the

view• The view is updated by making the model

observable and notifying the view classes when changes occur in the model

Page 153: Chapter 9 Observer

153

• Both listening and observing occur in the design

• The reality is that observing is just another kind of listening

• Having both listening and observing, practically speaking, “two stages of listening”, makes it possible to separate the view and the controller

Page 154: Chapter 9 Observer

154

• It is also worth noting that the view and the controller are both graphical in nature

• The controller is a slider, which is displayed• The view, the graph panels and the label, plus

the controller, the slider, are all displayed together in a common panel, ShowBallistics3

Page 155: Chapter 9 Observer

155

• In the simple CSCE 202 type approach, you had one listener, with access to the model and the view

• Here, the graphical object, JSlider, which is the controller, has its own listener, which updates the model

• The observer machinery means that the view components are notified of the changes in the model and can change accordingly

Page 156: Chapter 9 Observer

156

A Nicer Picture

• Even though it might not have been clear from the preceding diagram, separating the model, view, and controller into different classes can lead to a cleaner diagram as well as design

• The book refers now to a business layer (model) and a GUI layer (view) in the design

• Classes in the same layer will have similar responsibilities or roles in the application

Page 157: Chapter 9 Observer

157

• In a layered design, the upper layers should depend on the lower layers

• There is some kind of (generic) interface between layers

• A longer-range consequence of this kind of design is that different layers may eventually lead not just to different classes, but to different packages in the overall architecture

Page 158: Chapter 9 Observer

158

• A diagram illustrating layers is given on the overhead following the next one

• This is a simplified diagram of the model and the view and their relationship

• It is simplified because it doesn’t explicitly show the controller

Page 159: Chapter 9 Observer

159

• In the diagram, dashed lines with open arrowheads link the panels and label to Tpeak

• This UML symbol means “has or makes use of” (in this case, “observes”)

• The dashed lines mean that the Tpeak object is not an instance variable of the objects that have or make use of it

Page 160: Chapter 9 Observer

160

Page 161: Chapter 9 Observer

161

• On the following overhead is a more complete diagram of the BallisticsLabel class and the Observer interface, which it implements

• A class that implements the Observer interface has to implement the update() method

• The first parameter of the method is a reference to the object it observes

Page 162: Chapter 9 Observer

162

Page 163: Chapter 9 Observer

163

Continuing the Book’s Example—An Observable Model Class

• We’re now ready to consider code for the redesigned application

• The model will be factored out as the Tpeak class• The key point is this:• The model will be made observable• Code for this class is shown on the following

overheads, with one explanatory comment added

Page 164: Chapter 9 Observer

164

• import java.util.Observable;• public class Tpeak extends Observable• {• protected double value;• public Tpeak(double value)• {• this.value = value;• }

Page 165: Chapter 9 Observer

165

• public double getValue()• {• return value;• }

• /* The last two lines of this method• are the key point. When you change the• value in the model, you notify the• observers. Both lines of code are• needed. When they are executed, the• update() method of any observer object• that has been added to this observable• object will be called. */

• public void setValue(double value)• {• this.value = value;• setChanged();• notifyObservers();• }• }

Page 166: Chapter 9 Observer

166

• There are two things to notice about this code:

• 1. It is the set() method where the effects of observability appear

• After you change the value, you call setChanged()

• Then you call notifyObservers()

Page 167: Chapter 9 Observer

167

• 2. Notice that none of what is done in this class is actually application specific

• This could be an observable instance of just about anything

• Later, this will be the basis of yet another redesign

• For the time being, we need to complete the current redesign, including observer(s) to match the observable class

Page 168: Chapter 9 Observer

• Challenge 9.4• “Write the complete code for BallisticsLabel.java.”• Comment mode on:• In other words, write the code for something that

observes Tpeak• As usual, the simplest approach is just to look at

what the book did• Explanatory comments have been added to the

code

168

Page 169: Chapter 9 Observer

• import javax.swing.*;• import java.util.*;• public class BallisticsLabel extends JLabel implements

Observer• {

• /* BallisticsLabel is an observer.• Tpeak is observable. At construction• time, the label is added as an observer• of peak. It seems that constructing• the observer and the observable object• and adding the observer could be done• in client code rather than by passing• the parameter as done here. */

• public BallisticsLabel (Tpeak tPeak)• {• tPeak.addObserver(this);• }

169

Page 170: Chapter 9 Observer

170

• /* The call to notifyObservers() in• Tpeak is what triggers the call to update()• on the observer. Notice that a reference• to the observed object is automatically• passed. This is reminiscent of passing• an event to a listener. The API documentation• doesn’t really explain the second parameter.• We simply ignore it. */

• public void update(Observable o, Object arg)• {• setText(“” + ((Tpeak) o).getValue());• repaint();• }• }

Page 171: Chapter 9 Observer

• 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()

171

Page 172: Chapter 9 Observer

• 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

172

Page 173: Chapter 9 Observer

173

• 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

• Think back to the concept of layers and the diagram that showed the parts of the application in layers.

• It is the observer machinery that makes communication between the layers possible

Page 174: Chapter 9 Observer

174

A Callback Sequence

• Notice how notifyObservers() and update() are analogous in some sense to repaint() and paintComponent() as a callback sequence

• Maybe more to the point, notifyObservers() and update() are analogous to an event and an actionPerformed() method

• You make a call on one method• The end result is a call on another method

elsewhere in your code

Page 175: Chapter 9 Observer

175

Adding in the JSlider and its ChangeListener

• So, to provide the last piece of the puzzle, it’s necessary to consider the implementation of the slider

• The construction of the slider is contained in this method in the ShowBallistics3 class:

• public class JSlider slider()

Page 176: Chapter 9 Observer

176

• The book takes up the implementation of this method now

• It points out that it will implement the ChangeListener belonging to the slider as an anonymous (inner) class

Page 177: Chapter 9 Observer

177

• You may recall that the anonymous inner class syntax was mentioned in CSCE 202

• By definition, anonymous classes may be somewhat cryptic, so I don’t find them desirable

• This book uses this syntax, so at the very least it’s necessary to understand it when you see it, even if you choose not to use it yourself

Page 178: Chapter 9 Observer

178

• 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:”

Page 179: Chapter 9 Observer

179

• Comment mode on:• The t peak object and the slider object are both

instance variables in ShowBallistics3• This means that code for the slider will have access

to the variable t peak• Logically the model and controller are implemented

in separate classes, and the view depends on observability, but structurally, the model and view objects exist together in the ShowBallistics3 class

Page 180: Chapter 9 Observer

180

• Structurally, the controller has direct access to the model

• Syntactically, if you use an anonymous inner class, when you construct an instance of it, you also write its methods

• You have to implement the changeListener() method for the slider

• In other words, you have to determine what will happen in the application when the user moves the slider

Page 181: Chapter 9 Observer

181

• In CSCE 202 you typically implemented an actionPerformed() method for a listener

• On the other hand, mouseClicked() was specific to mice, for example

• In this code, a ChangeListener for a slider requires a stateChanged() method

• The incomplete code for this challenge is shown on the next overhead

Page 182: Chapter 9 Observer

182

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

Page 183: Chapter 9 Observer

183

• Solution 9.5• “One solution is:”• Comment mode on:• The complete slider code is not repeated• What is given on the following overhead is the

single Java statement containing the anonymous ChangeListener

• It consists of multiple lines of code

Page 184: Chapter 9 Observer

184

• slider.addChangeListener(new ChangeListener()

• {• public void stateChanged(ChangeEvent e)• {• if(sliderMax == sliderMin) return;• tPeak.setValue(• (slider.getValue() – sliderMin)• / (sliderMax – sliderMin));• }• });

Page 185: Chapter 9 Observer

185

• 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

• In other words, the model is updated• (The “if” statement is moderately bogus…)

Page 186: Chapter 9 Observer

186

The Overall Flow of Events

• 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

Page 187: Chapter 9 Observer

187

• In other words, change is initiated in the upper, GUI layer, by means of the visual controller part of the application

• This is propagated to the lower, business, or model layer

• It is propagated back up to the GUI layer by means because the view is visual and observes changes in the model

Page 188: Chapter 9 Observer

188

• Challenge 9.6• “Fill in the messages in Figure 9.5.”

Page 189: Chapter 9 Observer

189

Page 190: Chapter 9 Observer

190

• Solution 9.6• “Figure B.9 shows the calls that flow when a

user moves the slider in the ballistics application.”

Page 191: Chapter 9 Observer

191

Page 192: Chapter 9 Observer

192

• 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

Page 193: Chapter 9 Observer

193

Benefits of the MVC Pattern

• The book makes several observation about how division of responsibility in a design supports flexibility

• 1. A clean division between M, V, and C would make it possible to add a completely new GUI to a system without changing the model

• The book suggests adding a GUI for a handheld device, for example

Page 194: Chapter 9 Observer

194

• 2. An existing GUI may be modified with requiring changes to the rest of the design

• For example, a new controller in the GUI layer might be hooked in to change the value of Tpeak

• If so, the changes to the model will automatically propagate to the view

• It will not be necessary to recode the viewing mechanism

Page 195: Chapter 9 Observer

195

• 3. It also makes it possible to make changes at the business level

• Relying on the idea of encapsulation, as long as the public interface of the model remains the same, changes in its internal implementation do not require changes in the GUI, whether controller or view components

Page 196: Chapter 9 Observer

196

• 4. 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

Page 197: Chapter 9 Observer

197

• 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

Page 198: Chapter 9 Observer

198

Maintaining an Observable Object

• I’m not going to cover this topic in detail• You will not be responsible for being able to

apply any of the ideas in this section• Still, it’s worthwhile to know about these ideas

in case you need them in the future

Page 199: Chapter 9 Observer

199

• It breaks down into two separate areas:• What do you do if you can’t make something

observable?• What is PropertyChangeSupport?

Page 200: Chapter 9 Observer

200

What to do When Something Can’t be made Observable

• Notice that as presented so far, the pattern is implemented by extending the Observable class

• The question arises, what do you do if the thing you want to be observable already extends another class?

• The answer is similar to the answer when the same question arises with threads

Page 201: Chapter 9 Observer

201

• The thing that should be observable in the design is given an observable object as an instance variable

• In other words, you encapsulate the responsibility for observability characteristics in this other object

• Calls on the original object are passed or forwarded to the observable object as necessary

Page 202: Chapter 9 Observer

202

PropertyChangeSupport

• The Java API contains a class named PropertyChangeSupport

• Along with this there is an interface named PropertyChangeListener

• Roughly speaking, they are analogous to Observable and Observer

• In other words, they provide an alternative approach to implementing the pattern

Page 203: Chapter 9 Observer

203

• The UML diagram on the following overhead illustrates the relationship between an instance of Component, PropertyChangeSuppport, and PropertyChangeListener

• Notice that this parallels the idea just presented about observable objects

• The component itself doesn’t extend PropertyChangeSupport

• It has an object which extends that class

Page 204: Chapter 9 Observer

204

Page 205: Chapter 9 Observer

205

• This general idea came up before:• How much information does the listener know

about what has happened?• The book now introduces the ideas of push and

pull• Push suggests that information is pushed to the

listener• Pull suggests that the listener has to inquire

about what happened

Page 206: Chapter 9 Observer

206

• Varying degrees of these approaches can be implemented with PropertyChangeListener

• Push implies listeners are more tightly coupled with the object of interest

• Pull implies a more general design, with looser coupling

• All of this knowledge may become important in the future if you end up writing an advanced application with a GUI

Page 207: Chapter 9 Observer

207

Another Example

• There is no “other” example for this unit

Page 208: Chapter 9 Observer

208

Lasater’s UML Diagram

• I don’t find Lasater’s diagram helpful for this unit, but it’s included for the sake of completeness

Page 209: Chapter 9 Observer

209

Page 210: Chapter 9 Observer

210

The End