C OMP 401 P RACTICAL A PPLICATIONS OF MVC AND O BSERVER : P ROPERTY N OTIFICATION Instructor: Prasun Dewan.

Slides:



Advertisements
Similar presentations
11 Copyright © 2005, Oracle. All rights reserved. Using Arrays and Collections.
Advertisements

INHERITANCE BASICS Reusability is achieved by INHERITANCE
C OMP 110 S TATE Instructor: Jason Carter. 2 O UTLINE Instance Variables Procedures Properties Print Statements Println vs. Print Overloading.
C OMP 110/401 C OLLECTION K INDS Instructor: Prasun Dewan.
Recitation 11 November 11, Today’s Goals:  Automatic refresh  Learn and apply the Observer pattern.
C OMP 110 A RRAYS Instructor: Jason Carter. 2 O UTLINE for loops Arrays.
C OMP 401 D YNAMIC D ISPATCH AND A BSTRACT M ETHODS Instructor: Prasun Dewan.
C OMP 110 R EPRESENTATION Instructor: Jason Carter.
C OMP 110 S TYLE Instructor: Jason Carter. 2 I NTERFACES AND M ORE S TYLE Define contracts between our users and implementers Optional – they may not.
C OMP 110 L OOPS Instructor: Jason Carter. 2 L OOPS More loops Off-by-one errors Infinite loops Nested Loops Animations Concurrency Synchronized methods.
C OMP 110 L OAN C ASE S TUDY Instructor: Jason Carter.
Mari Göransson - KaU - Datavetenskap - DAVD11 1 Java Beans - Events and Properties -
Road Map Introduction to object oriented programming. Classes
Model View Controller Prasun Dewan Comp 114. Model View Controller Pattern Issue –How to create user-interface objects like object editor Model-View-Controller.
By - Qiong Han. DON’T FALL BEHIND IN READING Submission Instruction Everyone needs to submit the printed HARD- COPY of the codes and the grading sheets.
Midterm Exam 75 points 1 min per point Allocate time proportionate to points Closed book Chapters 1-5 (except char) PDF/PS with index and corrections coming.
Program Style Identifier Names Comments Named Constants Avoiding Code Repetition Giving Least Privilege Efficiency Interfaces.
Comp 14 (3) By Stephan Sherman Office hours, W, 3:00-3:50pm.
1 org.eclipse.ui.texteditor-api l Provides a framework for text editors obeying to the desktop rules. org.eclipse.ui.texteditor.
Programmer-Defined Types Object Types as Programmer-defined Types Two-way Dependencies Representation Errors Primitive Vs Object Properties Constructors.
Terms and Rules Professor Evan Korth New York University (All rights reserved)
ObjectEditor Prasun Dewan Comp 114. ObjectEditor Automatic user-interface generation. You only write computation code Separate object to do I/O Main just.
C OMP 110 M ODEL -V IEW -C ONTROLLER MVC Instructor: Jason Carter.
State Instance Variables Procedures Properties Print Statements Println Vs Print Overloading J++
REFACTORING Lecture 4. Definition Refactoring is a process of changing the internal structure of the program, not affecting its external behavior and.
Introduction to Object Oriented Programming. Object Oriented Programming Technique used to develop programs revolving around the real world entities In.
C OMP 401 P ATTERNS, I NTERFACES AND O BJECT E DITOR Instructor: Prasun Dewan.
Programming in Java Unit 2. Class and variable declaration A class is best thought of as a template from which objects are created. You can create many.
C OMP 110/401 C OMPOSITE A NNOTATIONS Instructor: Prasun Dewan.
Chapter 3 Syntax, Errors, and Debugging Fundamentals of Java.
C OMP 401: C ONSTRUCTORS AND P OINTERS Instructor: Prasun Dewan (FB 150,
Java Classes Chapter 1. 2 Chapter Contents Objects and Classes Using Methods in a Java Class References and Aliases Arguments and Parameters Defining.
Components Components are specialized self contained Software entities that can be replicated, Customized and inserted into applications. Components come.
C OMP 110/401 E NCAPSULATION AND L EAST P RIVILEGE Instructor: Prasun Dewan.
An Introduction to Programming and Object Oriented Design using Java 3 rd Edition. Dec 2007 Jaime Niño Frederick Hosch Chapter 18 Integrating user interface.
C OMP 401 A DVANCED G ENERICS Instructor: Prasun Dewan.
First Bean Compose SimpleBean Demo Simple Bean Discuss Manifest and Jar Add Properties to SimpleBean.
A NATOMY OF AN I NTERACTIVE A PPLICATION Prasun Dewan Department of Computer Science University of North Carolina at Chapel Hill Code.
Liang, Introduction to Java Programming, Sixth Edition, (c) 2005 Pearson Education, Inc. All rights reserved Chapter 27 JavaBeans and.
COP3502 Programming Fundamentals for CIS Majors 1 Instructor: Parisa Rashidi.
OBSERVER DESIGN PATTERN. Behavioral Patterns  Behavioral patterns are those patterns that are most specifically concerned with communication between.
Java Class Structure. Class Structure package declaration import statements class declaration class (static) variable declarations* instance variable.
C OMP 401 A NIMATION : MVC Instructor: Prasun Dewan.
C OMP 401 U SER -I NTERFACE VS. M AIN T HREADS Instructor: Prasun Dewan.
C OMP 401 R EFLECTION AND A CTION O BJECTS Instructor: Prasun Dewan.
C OMP 401 G RAPH VS. D AG VS. T REE O BJECT S TRUCTURES Instructor: Prasun Dewan.
Introduction to Java Beans From Anders Børjesson.
Liang, Introduction to Java Programming, Seventh Edition, (c) 2009 Pearson Education, Inc. All rights reserved Chapter 32 JavaBeans and Bean.
Chapter 11: Advanced Inheritance Concepts. Objectives Create and use abstract classes Use dynamic method binding Create arrays of subclass objects Use.
Java Beans - Basics CIS 421 Web-based Java Programming.
C OMP 110/401 D OCUMENTATION : A NNOTATIONS Instructor: Prasun Dewan.
C OMP 401 C OPY : S HALLOW AND D EEP Instructor: Prasun Dewan.
Recitation 5 September 23, As you come in...  Please sit next to someone you will collaborate with for today’s recitation.  Choose someone with.
C# Programming: From Problem Analysis to Program Design1 Creating Your Own Classes C# Programming: From Problem Analysis to Program Design 4th Edition.
Classes CS 162 (Summer 2009). Parts of a Class Instance Fields Methods.
Chapter 5 Introduction to Defining Classes Fundamentals of Java.
C OMP 401 D YNAMIC D ISPATCH AND V IRTUAL AND A BSTRACT M ETHODS Instructor: Prasun Dewan.
Chapter 32 JavaBeans and Bean Events
Chapter 36 JavaBeans and Bean Events
Instructor: Prasun Dewan
Inheritance "Question: What is the object oriented way of getting rich? Answer: Inheritance.“ “Inheritance is new code that reuses old code. Polymorphism.
Comp 401 Dynamic Dispatch and Virtual and Abstract Methods
Persistence & Bean Properties
Object Oriented Programming in java
Recitation 4 September 16, 2011.
Comp 401 Concluding Remarks
Review Session Biggest discrepancy questions
Recitation 10 November 3, 2011.
Recitation 3 September 9, 2011 Wade Gobel.
Properties and Collections
Presentation transcript:

C OMP 401 P RACTICAL A PPLICATIONS OF MVC AND O BSERVER : P ROPERTY N OTIFICATION Instructor: Prasun Dewan

2 P REREQUISITES MVC Composite Objects Shapes

3 I NTERFACE I MPLEMENTATION public class ABMISpreadsheet implements BMISpreadsheet { double height; double weight; public ABMISpreadsheet(double theInitialHeight, double theInitialWeight) { setHeight(theInitialHeight); setWeight(theInitialWeight); } public double getWeight() { return weight; } public void setWeight(double newWeight) { weight = newWeight; } public double getHeight() { return height; } public void setHeight(double newHeight) { height = newHeight; } public double getBMI() { return weight/(height*height); }

4 R EFRESHING O BJECT E DITOR FROM M AIN public class ABMISpreadsheetRefreshedByMain { public static void main (String[] args) { BMISpreadsheet bmiSpreadsheet = new ABMISpreadsheet(); OEFrame oeFrame = ObjectEditor.edit(bmiSpreadsheet); bmiSpreadsheet.setHeight(1.77); bmiSpreadsheet.setWeight(75); oeFrame.refresh(); } How to apply MVC ? Read Methods Write Methods Model View Controller Notification Method Observer Registration Method

5 A PPLYING I DEA MVC TO O BJECT E DITOR Read Methods Write Methods Model OE View OE Controller Performs Input Performs Output Notification Method Observer Registration Method Edited objects are now observables Need to decide on the notification and registration methods

6 A DAPT T HIS H OW ? Must use general (de)registration method Must use general listener type public interface java.util.Observer { public void update(Observable o, Object arg); } public class java.util.Observable { public void addObserver(Observer o) { … }; public void notifyObservers() { … }; }

7 C HANGES ? public class ABMISpreadsheet implements BMISpreadsheet { double height; double weight; public ABMISpreadsheet(double theInitialHeight, double theInitialWeight) { setHeight(theInitialHeight); setWeight(theInitialWeight); } public double getWeight() { return weight; } public void setWeight(double newWeight) { weight = newWeight; } public double getHeight() { return height; } public void setHeight(double newHeight) { height = newHeight; } public double getBMI() { return weight/(height*height); }

8 S TANDARD S INGLE FINE - GRAINED UPDATE METHOD import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import util.annotations.ObserverRegisterer; import util.annotations.ObserverTypes; import util.models.PropertyListenerRegisterer; public class AnObservableBMISpreadsheet implements BMISpreadsheet, PropertyListenerRegisterer { PropertyListenerSupport propertyListenerSupport = new public void addPropertyChangeListener( PropertyChangeListener listener) { propertyListenerSupport.addElement(listener); } … public void setWeight(double newWeight) { double oldWeight = weight; double oldBMI = getBMI(); weight = newWeight; if (propertyListenerSupport != null) { propertyListenerSupport.notifyAllListeners( new PropertyChangeEvent(this, "weight", oldWeight, newWeight)); propertyListenerSupport.notifyAllListeners( new PropertyChangeEvent(this, "bmi", oldBMI, getBMI())); } Standard Bean Listener Signature Standard event Standard registration support To prevent erroneous signature

9 S TANDARD R EGISTRATION S IGNATURE package util.models; import java.beans.PropertyChangeListener; public interface PropertyListenerRegisterer { void addPropertyChangeListener( PropertyChangeListener aListener); }

10 S UPPORT I MPLEMENTATION ? import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import util.annotations.ObserverRegisterer; import util.annotations.ObserverTypes; import util.models.PropertyListenerRegisterer; public class AnObservableBMISpreadsheet implements BMISpreadsheet, PropertyListenerRegisterer { PropertyListenerSupport propertyListenerSupport = new public void addPropertyChangeListener( PropertyChangeListener listener) { propertyListenerSupport.addElement(listener); } … public void setWeight(double newWeight) { double oldWeight = weight; double oldBMI = getBMI(); weight = newWeight; if (propertyListenerSupport != null) { propertyListenerSupport.notifyAllListeners( new PropertyChangeEvent(this, "weight", oldWeight, newWeight)); propertyListenerSupport.notifyAllListeners( new PropertyChangeEvent(this, "bmi", oldBMI, getBMI())); } Standard registration support No need to subclass to get automatic notification as in Observable

11 H ISTORY + N OTIFY A LL public class APropertyListenerSupport implements PropertyListenerSupport { public final int MAX_SIZE = 50; PropertyChangeListener[] contents = new PropertyChangeListener[MAX_SIZE]; int size = 0; public int size() { return size; } public PropertyChangeListener elementAt (int index) { return contents[index]; } boolean isFull() { return size == MAX_SIZE; } public void addElement(PropertyChangeListener l) { if (isFull()) System.out.println("Adding item to a full history"); else { contents[size] = l; size++; } public void notifyAllListeners(PropertyChangeEvent event) { for (int index = 0; index < size(); index++) { elementAt(index).propertyChange(event); } Modelled after standard Java PropertyChangeSupport

12 S TANDARD L ISTENER AND E VENT package java.beans; public interface PropertyChangeListener { public void propertyChange (PropertyChangeEvent evt); } package java.beans; public class PropertyChangeEvent extends java.util.EventObject { public PropertyChangeEvent (Object source, String propertyName, Object oldValue, Object newValue) {…} public Object getNewValue() {…} public Object getOldValue() {…} public String getPropertyName() {…} …. } Needed only if you are defining your own view/observable

13 O BJECT E DITOR O BSERVER P ROTOCOL ObjectEditor implements the standard PropertyChangeListener interface public class ObjectEditorView implements PropertyChangeListener { public void propertyChange(PropertyChangeEvent event) {... }

14 C OMMUNICATING B EAN E VENTS Read Methods Write Methods propertyChange (PropertyChangeEvent ) addPropertyChangeListener (PropertyChangeListener ) Model OE View OE Controller

15 O BJECT E DITOR O BSERVER P ROTOCOL If the class of a displayed object defines the standard ypes. PROPERTY_LISTENER) public void addPropertyChangeListener (PropertyChangeListener l) Annotation or util.models.PropertyListenerRegisterer interface to ensure method signature is right ObjectEditor calls the method to register itself as an observer Method should store a reference to ObjectEditor and other observers Cannot define own PropertyChangeListener with same name and methods as predefined, ObjectEditor expects predefined interface

16 O BJECT E DITOR O BSERVER P ROTOCOL A property changing method can now call the propertyChange(PropertyChangeEvent arg) defined by PropertyChangeListener to inform ObjectEditor and other observers about change public void setWeight(double newWeight) { double oldWeight = weight; double oldBMI = getBMI(); weight = newWeight; propertyListenerSupport.notifyAllListeners( new PropertyChangeEvent(this, "weight", oldWeight, newWeight)); propertyListenerSupport.notifyAllListeners(new PropertyChangeEvent(this, "bmi", oldBMI, getBMI())); }

17 O BJECT E DITOR V IEW The implementation of this method in ObjectEditor updates the display public class ObjectEditorView implements java.beans.PropertyChangeListener { public void propertyChange (PropertyChangeEvent arg) { // update display of property arg.getPropertyName() // to show arg.getNewValue() … }

18 R EFRESHING O BJECT E DITOR FROM M AIN public class AnObservableBMISpreadsheetDemoer { public static void main (String[] args) { BMISpreadsheet bmiSpreadsheet = new AnObservableBMISpreadsheet(); ObjectEditor.edit(bmiSpreadsheet); bmiSpreadsheet.setHeight(1.77); bmiSpreadsheet.setWeight(75); } No warning now

19 C OMPOSITE O BJECTS ? public static void main (String[] args) { CartesianPlane cartesianPlane = new AnObservableCartesianPlane(200, 125, 125); ObjectEditor.edit(cartesianPlane); cartesianPlane.setAxesLength(100); } Which notifications should be sent?

20 public void setAxesLength(int anAxesLength) { axesLength = anAxesLength; xAxis.setWidth(axesLength); yAxis.setHeight(axesLength); xAxis.setX(toXAxisX()); xAxis.setY(toXAxisY()); yAxis.setX(toYAxisX()); yAxis.setY(toYAxisY()); xLabel.setX(toXLabelX()); xLabel.setY(toXLabelY()); yLabel.setX(toYLabelX()); yLabel.setY(toYLabelY()); } U NOBSERVABLE C ARTESIAN P LANE Need notification Notification only for atomic properties No notifications for composite properties/elements unless new object assigned to them New objects should be assigned if necessary

21 public class AnObservableCartesianPlane extends ACartesianPlane implements ObservableCartesianPlane { PropertyListenerSupport propertySupport = new APropertyListenerSupport(); public AnObservableCartesianPlane (int theAxesLength, int theOriginX, int theOriginY ) { super(theAxesLength, theOriginX, theOriginY); xAxis = new AnObservableLine(toXAxisX(), toXAxisY(), axesLength, 0); yAxis = new AnObservableLine(toYAxisX(), toYAxisY(), 0, axesLength); xLabel = new AnObservableStringShape ("X", toXLabelX(), toXLabelY()); yLabel = new AnObservableStringShape ("Y", toYLabelX(), toYLabelY()); } public void setAxesLength(int newVal) { int oldVal = getAxesLength(); super.setAxesLength(newVal); propertySupport.notifyAllListeners( new PropertyChangeEvent(this, "axesLength", oldVal, newVal)); } … } O BSERVABLE C ARTESIAN P LANE No notifications for composite properties/elements unless new object assigned to them

22 A TOMIC O BJECTS A NNOUNCING E VENT public void setX(int newX) { x = newX; } public void setX(int newVal) { int oldVal = getX(); super.setX(newVal); propertySupport.notifyAllListeners( new PropertyChangeEvent(this, "X", oldVal, newVal)); } If a single setX (anX) shared by all classes in a project, then a single X setter method must be changed. AStringShape AnObservableStringShape

23 T ARGETS OF R EGISTRATION M ETHOD OE View ObjectEditor creates an observer for each observable in the logical structure of the root object displayed to ObjectEditor.edit() addPropertyChange Listener() OE View

24 R EFRESHING O BJECTS WITH O BJECT P ROPERTIES Usually only primitive values refreshed Unless object properties/elements (must be) assigned new values Can result in multiple events being sent for the same high level action (resize axes in Cartesian Plane) If a composite value is announced ObjectEditor has to create a new set of views for the composite value which is likely to be more expensive than processing multiple notifications An ObjectEditor view registers itself as an observer of each observable in the logical structure of the object passed to ObjectEditor.edit()

25 A LTERNATIVE C OARSE -G RAINED O BSERVABLE public class AnInefficientObservableCartesianPlane extends ACartesianPlane implements ObservableCartesianPlane { PropertyListenerSupport propertySupport = new APropertyListenerSupport(); public AnInefficientObservableCartesianPlane ( int theAxesLength, int theOriginX, int theOriginY ) { super(theAxesLength, theOriginX, theOriginY); } public void setAxesLength(int newVal) { int oldVal = getAxesLength(); super.setAxesLength(newVal); propertySupport.notifyAllListeners(new PropertyChangeEvent(this, "axesLength", oldVal, newVal)); propertySupport. notifyAllListeners(new PropertyChangeEvent(this, "XAxis", xAxis, xAxis)); propertySupport. notifyAllListeners(new PropertyChangeEvent(this, "YAxis", yAxis, yAxis)); propertySupport.notifyAllListeners(new PropertyChangeEvent( this, "XLabel", xLabel, xLabel)); propertySupport.notifyAllListeners(new PropertyChangeEvent( this, "YLabel", yLabel, yLabel)); } } Ask ObjectEditor to recreate and redraw the axes and label! Inefficient, but will work All getters of label and lines will be called as view does not know which part of label/line changes. What if we announce some but not all changes

26 P ARTIALLY O BSERVABLE O BJECT An object may announce changes to only some of its properties A label may announce location change but not size changes. Only some of the values assigned to properties of an object may themselves announce changes Labels of ACartesianPoint may announce changes but not its Axes. For full autorefresh Every change in logical structure must be announced Tedious That is why ObjectEditor calls refresh after each method call

27 D EPENDENT V ALUES IN C HILDREN public void setAxesLength(int anAxesLength) { axesLength = anAxesLength; /* xAxis.setWidth(axesLength); yAxis.setHeight(axesLength); xAxis.setX(toXAxisX()); xAxis.setY(toXAxisY()); yAxis.setX(toYAxisX()); yAxis.setY(toYAxisY()); xLabel.setX(toXLabelX()); xLabel.setY(toXLabelY()); yLabel.setX(toYLabelX()); yLabel.setY(toYLabelY()); */ } What if component objects have readonly properties dependent on parent properties? Label and line have only getters defined in terms of parent axesLength and other variables.

28 public void setAxesLength(int anAxesLength) { axesLength = anAxesLength; … propertySupport. notifyAllListeners( new PropertyChangeEvent(xLabel, "X", oldXLabelX, xLabelX)); propertySupport. notifyAllListeners( new PropertyChangeEvent(xLabel, “Y", oldXLabelY, xLabelY)); … } A NNOUNCING C HILDREN D EPENDENT V ALUES Parent write method can announce changes to children properties

29 M AKING AN O BJECT A UTO R EFRESHABLE Do not call refresh() method of ObjectEditor, instead make all atomic shapes observable For each class C with one or more atomic properties do the following. Implement the util.models.PropertyListenerRegisterer interface This means you have to implement the addPropertyChangeListener (java.beans.PropertyChangeListener l) Delcare an instance variable of type PropertyListenerSupport holding an instance of APropertyListenerSupport addPropertyChangeListener will simply ask the PropertyListenerSupport instance to add the listener to its collection Announce property change events in the setters of atomic properties Create an instance of Java java.beans.PropertyChangeEvent to describe the change, giving it this(the object whose property was changed), propertyName, old property value, new property value Do not define your own PropertyChangeEvent with the same naming conventions! Ask the instance of PropertyListenerSupport to broadcast this event to all of the listeners it keeps track of Make sure a composite object does not create a new object in a getter for an object property.

30 C HANGE NOT R EFLECTED IN AN O BSERVER The class of the observable does not define a registration method. The observer does not call this method in the observer or calls it in is parent or child The observer is not sent changes to the component. The observer does not correctly react to the change. Use print statements or breakpoints to debug?

31 O BJECT E DITOR VS. Y OUR O WN O BSERVER ObjectEditor automatically registers with observable based on name and argument of registration method The argument must be predefined PropertyChangeListener You must write your own code to register observer

32 C OMMON S ITUATION IN P ARTIALLY O BSERVABLE O BJECT “Some value is refreshed correctly in the main window but not in the graphics window.” An object/property is either displayed in the graphics window or in the main window - not both. Point's x and y coordinates not displayed as text fields in the main window. Real problem: you have two copies of the same value, one displayed in the main window and one in the graphics window, and you have announced changes to the former and not the latter.

33 C OLLECTION N OTIFICATIONS ? public static void createAndDisplayHistory( StringHistory stringHistory) { ObjectEditor.edit(stringHistory); ThreadSupport.sleep (1000); stringHistory.addElement("James Dean"); stringHistory.addElement("Joe Doe"); stringHistory.addElement("Jane Smith"); stringHistory.addElement("John Smith"); }

34 H OW TO MAKE IT O BSERVABLE ? public class AStringHistory implements StringHistory { public final int MAX_SIZE = 50; String[] contents = new String[MAX_SIZE]; int size = 0; public int size() { return size;} public String elementAt ( int index) { return contents[index]; } boolean isFull() { return size == MAX_SIZE; } public void addElement(String element) { if (isFull()) System.out.println("Adding item to a full history"); else { contents[size] = element; size++; }

35 O BSERVABLE S TRING H ISTORY import util.models.VectorChangeEvent; import util.models.VectorListener; import util.models.VectorListenerRegisterer; public class AnObservableStringHistory implements StringHistory, VectorListenerRegisterer{ VectorListenerSupport vectorListenerSupport = new AVectorListenerSupport(); … public void addElement(String element) { if (isFull()) System.out.println("Adding item to a full history"); else { contents[size] = element; size++; vectorListenerSupport.notifyAllListeners( new VectorChangeEvent(this, VectorChangeEvent.AddComponentEvent, size -1, null, element, size)); public void addVectorListener(VectorListener aListener) { vectorListenerSupport.addElement(aListener); } …

36 V ECTOR C HANGE S UPPORT public class AVectorListenerSupport implements VectorListenerSupport { public final int MAX_SIZE = 50; VectorListener[] contents = new VectorListener[MAX_SIZE]; int size = 0; public int size() { return size; } public VectorListener elementAt (int index) { return contents[index]; } boolean isFull() { return size == MAX_SIZE; } public void addElement(VectorListener l) { if (isFull()) System.out.println("Adding item to a full history"); else { contents[size] = l; size++; } public void notifyAllListeners(VectorChangeEvent event) { for (int index = 0; index < size(); index++) { elementAt(index).updateVector(event); }

37 C OLLECTION N OTIFICATIONS Works for any variable sized collection defined using ObjectEditor convention (originally derived for Vectors) Read Methods Write Methods Performs Input Performs Output updateVector (VectorChangeEvent) addVectorListener(VectorListener) Model OE View OE Controller

38 V ECTOR L ISTENER AND V ECTOR L ISTENER R EGISTERER I NTERFACES package util.models; public interface VectorListener { public void updateVector(VectorChangeEvent evt); } package util.models; public interface VectorListenerRegisterer { public void addVectorListener( VectorListener aListener); }

39 V ECTOR C HANGE E VENT package util.models; public class VectorChangeEvent { Object source; Object otherSource; // constants for event types public static final int AddComponentEvent = 2 DeleteComponentEvent = 2, ChangeComponentEvent = 3, InsertComponentEvent = 4, CompletedComponentsEvent = 5, ClearEvent = 6, UndefEvent = 1000; // constructor, oldObject can be null when no value is replaced public VectorChangeEvent(Object theSource, int type, int posn, Object oldObject, Object newObject, int newSize) {..}

40 import util.models.VectorChangeEvent; import util.models.VectorListener; import util.models.VectorListenerRegisterer; public class AnObservableStringHistory implements StringHistory, VectorListenerRegisterer{ VectorListenerSupport vectorListenerSupport = new AVectorListenerSupport(); … public void addElement(String element) { if (isFull()) System.out.println("Adding item to a full history"); else { contents[size] = element; size++; vectorListenerSupport.notifyAllListeners( new VectorChangeEvent(this, VectorChangeEvent.AddComponentEvent, size -1, null, element, size)); public void addVectorListener(VectorListener aListener) { vectorListenerSupport.addElement(aListener); } … C OLLECTION N OTIFICATIONS public VectorChangeEvent(Object theSource, int type, int posn, Object oldObject, Object newObject, int newSize)

41 T ABLE ? // associates key with value, returning last value associated with key public put ( key, value); // returns last value associated with key, or null if no association public get ( key); // optional, removes associated value, and returns it or null public remove( key); Necessary but not sufficient to displays all keys and elements OE does not know the keys Object can announce each put (and optional remove)

42 T ABLE L ISTENER package util.models; public interface HashtableListener { public void keyPut(Object source, Object key, Object value, int newSize); public void keyRemoved(Object source, Object key, int newSize); }

43 T ABLE N OTIFICATIONS Works for any variable sized collection defined using ObjectEditor convention (originally derived for Vectors) Read Methods Write Methods Performs Input Performs Output updateVector (VectorChangeEvent) addHashtableListener(HashtableListener) Model OE View OE Controller

44 O BSERVERS Different forms of observers Some differences in syntax Using term “Listener” instead of “Observer” Some differences in amount of information conveyed to observer about change Send whole object Java Observer gets whole object, PropertyChangeListener gets property changed Different kinds of listeners for properties and list components Property changed vs. element inserted, deleted, replaced Some difference in generality of notification scheme update(ObservableCounter) cannot be invoked on ObjectEditor ObjectEditor cannot implement an observer interface defined by us.