unit 30 observer

191
Unit 30 Observer Summary prepared by Kirk Scott 1

Upload: jory

Post on 24-Feb-2016

34 views

Category:

Documents


0 download

DESCRIPTION

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. Think back to Wari and Togiz Kumalak The very first implementations weren’t graphical at all - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Unit 30 Observer

1

Unit 30Observer

Summary prepared by Kirk Scott

Page 2: Unit 30 Observer

2

Page 3: Unit 30 Observer

3

Page 4: Unit 30 Observer

4

Page 5: Unit 30 Observer

5

Page 6: Unit 30 Observer

6

Page 7: Unit 30 Observer

7

Page 8: Unit 30 Observer

8

Page 9: Unit 30 Observer

9

Design Patterns in JavaChapter 9Observer

Summary prepared by Kirk Scott

Page 10: Unit 30 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: Unit 30 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

• 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

Page 12: Unit 30 Observer

12

• 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 13: Unit 30 Observer

13

• 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 14: Unit 30 Observer

14

• 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 15: Unit 30 Observer

15

• 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 16: Unit 30 Observer

16

• 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

Page 17: Unit 30 Observer

17

• 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 18: Unit 30 Observer

18

• 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 19: Unit 30 Observer

19

• 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 20: Unit 30 Observer

20

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 21: Unit 30 Observer

21

• 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 22: Unit 30 Observer

22

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

• These are the constructs which support observability

Page 23: Unit 30 Observer

23

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

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

Page 24: Unit 30 Observer

24

• 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 25: Unit 30 Observer

25

• 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

Page 26: Unit 30 Observer

26

• 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

Page 27: Unit 30 Observer

27

• 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 28: Unit 30 Observer

28

• 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

Page 29: Unit 30 Observer

29

Observers and Multicasting

• Multicasting came up at the end of CS 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 30: Unit 30 Observer

30

• 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 31: Unit 30 Observer

31

• 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 32: Unit 30 Observer

32

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 33: Unit 30 Observer

33

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 which responds to events and changes application state

• Observers will then respond to the changes in state

Page 34: Unit 30 Observer

34

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

value• Above it there are two panels which depend

on changes to it

Page 35: Unit 30 Observer

35

Page 36: Unit 30 Observer

36

• 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

Page 37: Unit 30 Observer

37

• 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

Page 38: Unit 30 Observer

38

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

• tpeak will be explained on the following overheads

Page 39: Unit 30 Observer

39

• 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

Page 40: Unit 30 Observer

40

• 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

Page 41: Unit 30 Observer

41

• 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

Page 42: Unit 30 Observer

42

• 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

Page 43: Unit 30 Observer

43

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 44: Unit 30 Observer

44

Page 45: Unit 30 Observer

45

• 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 46: Unit 30 Observer

46

• 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 47: Unit 30 Observer

47

• 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

Page 48: Unit 30 Observer

48

• 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

Page 49: Unit 30 Observer

49

• 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 50: Unit 30 Observer

50

• 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 51: Unit 30 Observer

51

• 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 52: Unit 30 Observer

52

Code Challenges

• 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 53: Unit 30 Observer

53

• 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 54: Unit 30 Observer

54

Page 55: Unit 30 Observer

55

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 56: Unit 30 Observer

56

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 57: Unit 30 Observer

57

• 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

Page 58: Unit 30 Observer

58

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

Page 59: Unit 30 Observer

59

• 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

Page 60: Unit 30 Observer

60

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 61: Unit 30 Observer

61

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

Page 62: Unit 30 Observer

62

• 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

Page 63: Unit 30 Observer

63

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

• It is made mildly complicated by the fact that the slider is “owned by” the listener class

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

Page 64: Unit 30 Observer

64

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 65: Unit 30 Observer

65

Page 66: Unit 30 Observer

66

Provided incomplete code for stateChanged()

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

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

Page 67: Unit 30 Observer

67

• 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 68: Unit 30 Observer

68

• 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 69: Unit 30 Observer

69

• 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 70: Unit 30 Observer

70

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 71: Unit 30 Observer

71

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 72: Unit 30 Observer

72

• 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 73: Unit 30 Observer

73

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 74: Unit 30 Observer

74

• 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 75: Unit 30 Observer

75

• 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 76: Unit 30 Observer

76

• 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

Page 77: Unit 30 Observer

77

Page 78: Unit 30 Observer

78

• 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 79: Unit 30 Observer

79

• 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 CS 202 code, the actionPerformed()

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

Page 80: Unit 30 Observer

80

• 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

• There isn’t a clean division between model, view, and controller

Page 81: Unit 30 Observer

81

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 slider plays that role

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

Page 82: Unit 30 Observer

82

• 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

• Again, the claim is not made that this is bad, but in this sense it’s a monolithic design

Page 83: Unit 30 Observer

83

• Again, a comparison can be made with design choices from CS 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 84: Unit 30 Observer

84

• 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 85: Unit 30 Observer

85

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 Observer by changing the application design so that each component registered itself to receive changes to the slider

Page 86: Unit 30 Observer

86

• 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 87: Unit 30 Observer

87

• 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 88: Unit 30 Observer

88

Page 89: Unit 30 Observer

89

Page 90: Unit 30 Observer

90

• 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

Page 91: Unit 30 Observer

91

• The BallisticsPanel2 class implements the ChangeListener interface

• The panel for a graph, not ShowBallistics2, implements the ChangeListener interface

Page 92: Unit 30 Observer

92

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

• BallisticsLabel2 is a subclass of JLabel• BallisticsLabel2 also implements the

ChangeListener interface

Page 93: Unit 30 Observer

93

• 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

Page 94: Unit 30 Observer

94

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

• In CS 202, panels had listeners as inner classes• Here, the panels themselves implement the

ChangeListener interface• This example expands this out to include the

label• The general idea is that each graphical element

has listening capabilities associated with it

Page 95: Unit 30 Observer

95

Code for the New Design

• 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

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

• See the code on the next overhead

Page 96: Unit 30 Observer

96

• public BallisticsPanel2(BallisticsFunction func, JSlider slider)

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

Page 97: Unit 30 Observer

97

• 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 98: Unit 30 Observer

98

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

Page 99: Unit 30 Observer

99

• In the previous version of stateChanged() contained calls to setTPeak() on the panels

• Somewhere within that code painting was triggered

• In this version, tPeak is set directly, and the call to repaint() triggers a call to paintComponent()

• See the code on the next overhead

Page 100: Unit 30 Observer

100

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

Page 101: Unit 30 Observer

101

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

Page 102: Unit 30 Observer

102

• The stateChanged() method causes the relevant instance variables of the panel to be changed

• This is a change of state (model)• When the state changes, the call to repaint()

causes the visual representation to be updated to reflect that

Page 103: Unit 30 Observer

103

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 104: Unit 30 Observer

104

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 105: Unit 30 Observer

105

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

stateChanged() for the panel class• That method is relatively short and sweet

Page 106: Unit 30 Observer

106

• 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 107: Unit 30 Observer

107

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 the Tpeak object

Page 108: Unit 30 Observer

108

• According to the book, this change would result in a 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 were derived from tpeak anyway

• The graphics panels which listen for (observe) changes in the Tpeak object would be the view

Page 109: Unit 30 Observer

109

• 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

Page 110: Unit 30 Observer

110

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

• 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 111: Unit 30 Observer

111

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 responsible

• Classes should be self-contained—responsible for themselves

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

Page 112: Unit 30 Observer

112

• 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 113: Unit 30 Observer

113

• 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 114: Unit 30 Observer

114

• 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 115: Unit 30 Observer

115

• 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 116: Unit 30 Observer

116

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 117: Unit 30 Observer

117

• 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 118: Unit 30 Observer

118

The Observable Class

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

Page 119: Unit 30 Observer

119

• java.util • Class Observable

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

• public class Observable extends Object

Page 120: Unit 30 Observer

120

• 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 121: Unit 30 Observer

121

• 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 122: Unit 30 Observer

122

• 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 124: Unit 30 Observer

124

Notice the Italicized Method. It shows 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 125: Unit 30 Observer

125

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

• 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 126: Unit 30 Observer

126

Notice the Italicized Methods. They show up in the coming example.

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

• 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 127: Unit 30 Observer

127

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 129: Unit 30 Observer

129

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 130: Unit 30 Observer

130

• 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 131: Unit 30 Observer

131

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 132: Unit 30 Observer

132

• 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 133: Unit 30 Observer

133

Page 134: Unit 30 Observer

134

• Comment mode on:• This UML diagram isn’t as beautiful as it might be• However, it illustrates 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 135: Unit 30 Observer

135

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

• 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 136: Unit 30 Observer

136

• 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 137: Unit 30 Observer

137

• 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 138: Unit 30 Observer

138

• 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 139: Unit 30 Observer

139

• In the simple CS 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 140: Unit 30 Observer

140

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 141: Unit 30 Observer

141

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

• Different layers may eventually lead to different packages in the overall architecture

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

Page 142: Unit 30 Observer

142

• A diagram illustrating layers is given on the following overhead

• 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”) but indicates that the Tpeak object is not an instance variable of the objects that have or make use of it

Page 143: Unit 30 Observer

143

Page 144: Unit 30 Observer

144

• 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 145: Unit 30 Observer

145

Page 146: Unit 30 Observer

146

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 147: Unit 30 Observer

147

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

Page 148: Unit 30 Observer

148

• 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 149: Unit 30 Observer

149

• 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 150: Unit 30 Observer

150

• 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 151: Unit 30 Observer

• Challenge 9.4• “Write the complete code for

BallisticsLabel.java.”• Comment mode on:• As usual, the simplest approach is just to look

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

the code

151

Page 152: Unit 30 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);• }

152

Page 153: Unit 30 Observer

153

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

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

Page 154: Unit 30 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()

154

Page 155: Unit 30 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

155

Page 156: Unit 30 Observer

156

• 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 157: Unit 30 Observer

157

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

Page 158: Unit 30 Observer

158

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

• Recall that construction of the slider is packaged up in this method in the ShowBallistics3 class:

• public class JSlider slider()

Page 159: Unit 30 Observer

159

• 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

Page 160: Unit 30 Observer

160

• You may recall that the anonymous inner class syntax was mentioned in CS 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 161: Unit 30 Observer

161

• 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 162: Unit 30 Observer

162

• Comment mode on:• Keep in mind that 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

Page 163: Unit 30 Observer

163

• The key part of this is that when you write the code for the anonymous inner class, 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 164: Unit 30 Observer

164

• Do not be dismayed that the method is not named actionPerformed()

• This method is specific to sliders, just like mouseClicked() was specific to mice, for example

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

Page 165: Unit 30 Observer

165

• 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 166: Unit 30 Observer

166

• Solution 9.5• “One solution is:”• Comment mode on:• The comlete 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 167: Unit 30 Observer

167

• slider.addChangeListener(new ChangeListener()

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

Page 168: Unit 30 Observer

168

• 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

Page 169: Unit 30 Observer

169

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

• Change propagates from the upper, GUI, layer to the lower, business, layer and back again

Page 170: Unit 30 Observer

170

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

Page 171: Unit 30 Observer

171

Page 172: Unit 30 Observer

172

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

user moves the slider in the ballistics application.”

Page 173: Unit 30 Observer

173

Page 174: Unit 30 Observer

174

• 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 175: Unit 30 Observer

175

• 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

Page 176: Unit 30 Observer

176

• 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

Page 177: Unit 30 Observer

177

• 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 178: Unit 30 Observer

178

• 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 179: Unit 30 Observer

179

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 important to know about these ideas

in case you need them in the future

Page 180: Unit 30 Observer

180

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

observable?• What is PropertyChangeSupport?

Page 181: Unit 30 Observer

181

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 182: Unit 30 Observer

182

• The thing that in the design would otherwise be observable 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 183: Unit 30 Observer

183

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 184: Unit 30 Observer

184

• 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 185: Unit 30 Observer

185

Page 186: Unit 30 Observer

186

• 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 187: Unit 30 Observer

187

• Varying degrees of these approaches can be implemented with PropertyChangeListener

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

• Pull implies are 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 188: Unit 30 Observer

188

Another Example

• There is no “other” example for this unit

Page 189: Unit 30 Observer

189

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 190: Unit 30 Observer

190

Page 191: Unit 30 Observer

191

The End