Observer and Observable An Introduction To The Observer Interface and Observable Class Using The Model/View/Controller Architecture As A Guide
Observer and Observable An Introduction To The Observer Interface and Observable Class Using The Model/View/Controller Architecture As A Guide
Summary
Here's an introduction to the Observer interface and the
Observable class found in the Java programming language class
library. This article describes both and demonstrates how they
can be used to implement programs based on the
Model/View/Controller architecture introduced and popularized
by the Smalltalk programming language. (2,200 words)
Here's the problem: You're designing a program that will render data
describing a three-dimensional scene in two dimensions. The program must
be modular and must permit multiple, simultaneous views of the same scene.
Each view must be able to display the scene from a different vantage point,
under different lighting conditions. More importantly, if any portion of the
underlying scene changes, the views must update themselves.
None of these requirements presents an insurmountable programming
challenge. If the code that handles each requirement had to be written de
novo, however, it would add significant work to the overall effort. Fortunately,
support for these tasks is already provided by the Java class library in the
form of interface Observer and class Observable. The functionalities of these
two were inspired, in part, by the requirements of the Model/View/Controller
architecture.
The Model/View/Controller architecture
The Model/View/Controller architecture was introduced as part of the
Smalltalk-80 version of the Smalltalk programming language (a popular
object-oriented programming language invented by Alan Kay). The
Model/View/Controller architecture was designed to reduce the programming
effort required to build systems that made use of multiple, synchronized
presentations of the same data. Its central characteristics are that the model,
the controllers, and the views are treated as separate entities, and that
changes made to the model should be reflected automatically in each of the
views.
In addition to the program example described in the opening paragraph
above, the Model/View/Controller architecture may be used for projects such
as the following:
1
Figure 1: The Model/View/Controller architecture
The Model/View/Controller architecture has several benefits:
2
The central piece of the system is the model of the three-dimensional scene.
The model is a mathematical description of the vertices and the faces that
make up the scene. The data describing each vertex or face can be modified
(perhaps as the result of user input or a scene distortion or morphing
algorithm). However, there is no notion of point of view, method of display
(wireframe or solid), perspective, or light source. The model is a pure
representation of the elements that make up the scene.
The portion of the program that transforms the data in the model into a
graphical display is the view. The view embodies the actual display of the
scene. It is the graphical representation of the scene from a particular point
of view, under particular lighting conditions.
The controller knows what can be done to the model, and implements the
user interface that allows that action to be initiated. In this example, a data
entry control panel might allow the user to add, modify, or delete vertices
and faces.
Observer and Observable
The Java programming language provides support for the
Model/View/Controller architecture with two classes:
These two classes can be used to implement much more than just the
Model/View/Controller architecture. They are suitable for any system wherein
objects need to be automatically notified of changes that occur in other
objects.
Typically, the model is a subtype of Observable and the view is a subtype of
observer. These two classes handle the automatic notification function of the
Model/View/Controller architecture. They provide the mechanism by which
the views can be automatically notified of changes in the model. Object
references to the model in both the controller and the view allow access to
data in the model.
Observer and Observable functions
The following are code listings for observer and observable functions:
Observer
public void update(Observable obs, Object obj)
Called when a change has occurred in the state of the observable.
Observable
public void addObserver(Observer obs)
Adds an observer to the internal list of observers.
public void deleteObserver(Observer obs)
Deletes an observer from the internal list of observers.
public void deleteObservers()
Deletes all observers from the internal list of observers.
public int countObservers()
Returns the number of observers in the internal list of observers.
protected void setChanged()
Sets the internal flag that indicates this observable has changed state.
protected void clearChanged()
Clears the internal flag that indicates this observable has changed
state.
public boolean hasChanged()
Returns the boolean value true if this observable has changed state.
public void notifyObservers()
3
Checks the internal flag to see if the observable has changed state and
notifies all observers.
public void notifyObservers(Object obj)
Checks the internal flag to see if the observable has changed state and
notifies all observers. Passes the object specified in the parameter list
to thenotify() method of the observer.
How to use interface Observer and class Observable
The following section describes in detail how to create a new observable class
and a new observer class, and how to tie the two together.
Extend an observable
A new class of observable objects is created by extending class Observable.
Because class Observable already implements all of the methods necessary
to provide the observer/observable behavior, the derived class need only
provide some mechanism for adjusting and accessing the internal state of the
observable object.
In the class ObservableValue listing below, the internal state of the model is
captured by the integer n. This value is accessed (and, more importantly,
modified) only through public accessors. If the value is changed, the
observable object invokes its own setChanged() method to indicate that the
state of the model has changed. It then invokes its
own notifyObservers() method in order to update all of the registered
observers.
import java.util.Observable;
public ObservableValue(int n)
{
this.n = n;
}
setChanged();
notifyObservers();
}
Implement an observer
A new class of objects that observe the changes in state of another object is
created by implementing the Observer interface. The Observer interface
requires that an update() method be provided in the new class.
The update() method is called whenever the observable changes state and
announces this fact by calling its notifyObservers() method. The observer
should then interrogate the observable object to determine its new state,
and, in the case of the Model/View/Controller architecture, adjust its view
appropriately.
4
In the following class TextObserver listing, the notify() method first checks to
ensure that the observable that has announced an update is the observable
that this observer is observing. If it is, it then reads the observable's state,
and prints the new value.
import java.util.Observer;
import java.util.Observable;
ov.addObserver(to);
}
5
1. First the user manipulates a user interface component representing a
controller. The controller makes a change to the model via a public
accessor method -- which is setValue() in the example above.
2. The public accessor method modifies the private data, adjusts the
internal state of the model, and calls its setChanged() method to
indicate that its state has changed. It then calls notifyObservers() to
notify the observers that it has changed. The call
to notifyObservers() could also be performed elsewhere, such as in an
update loop running in another thread.
3. The update() methods on each of the observers are called, indicating
that a change in state has occurred. The observers access the model's
data via the model's public accessor methods and update their
respective views.
A demonstration
The example in Figure 3 demonstrates how observables and observers
typically work together in the Model/View/Controller architecture.
observer-pattern-in-java
Continuing to update knowledge about design patterns today we will see
widely used and popular Observer Pattern.
Wikipedia Says:
Observer Pattern is used to observe the state of an object in a program. It
relates to the principle of Implicit Invocation.
Implicit invocation: System may be structured around event handling using
a form of callback.It closely relates to inversion of control what is also known
as Hollywood Principle(Donot call us we will call you) which means instead of
programmer specifying function calls i.e a series of events to happen,
6
they would rather register desired responses to particular happenings.
Hence one or more Objects(Observers or listeners) are registered with
Subject to raise an event.
Responsibilities of Subject:
a) Subject can add, remove and notify observers .All observers should
register with Subject by means of some utilityMethod say addObserver().
Similarly observers may be removed to means of any utility method like
removeObserver().
b) An Observer may be notified of changes by notify() and notifyAll() which
notifies all observers.
Responsibilities of Observer:
a) All subclasses of class Observer(Ideally Observer class may be an abstract
class so that subclasses can define the implementation of notify() method.
As you have observed Observer Pattern defines one-to-many relationship
between subject-observers.
One Advantage of Observer Pattern is it decouples the observer from the
subject.
Consequences Of Observer Pattern
- Unknown Updates: Observers has no knowledge about each other and
update dependency can be hard to track down.
Observer Pattern In Java:
Java Provides builtin classes Observer and Observable to achieve this
functionality.AWT/Swing event model uses ObserverPattern to large extend
especially in event handling.
Below example shows one usage of Observer pattern.For Example we may
need to send all Admin Previlage Users Profiles to our CEO in our
organisation.
addObserver(employeeObserver);
String name;
7
//.....
boolean isAdmin;
EmployeeObserver() {
employeeList=new Vector<EmployeeTO>();
}
for(int i=1;i<=5;i++) {
EmployeeTO employeeTO=new EmployeeTO();
employeeTO.setName("Name:" + i);
employeeTO.setAdmin((i%2)==0);
employeeObserver.addEmployee(employeeTO);
}
// Notify All Admin Users.
adminUsers.notifyAdminUsers(employeeObserver);
}
}