Example
1: Contracts vs Observer
This example is a first, simple introduction to coordination contracts. The aims of the case study are the following:
The observer pattern and its variations [1] are very widely used in various classes of applications. A very common case is in graphical-user interfaces in order to separate the presentational aspects of the UI from the underlying data (model-view architecture). The intent of the pattern is to define a one to many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically. The basic structure of the pattern is the following:

Listing 1. Value.java, the ConcreteObservable
/*
** Value.java
**
** ConcreteObserver class for the SlideValue example
**
*/
import java.util.Observable;
class Value extends Observable {
private float value;
public void setValue(float _value) {
setChanged();
value = _value;
notifyObservers();
clearChanged();
}
public float getValue() {
return value;
}
}
Listing 2. The definition of classObservable.
package java.util;
public class Observable {
public synchronized void addObserver(Observer o);
public synchronized void deleteObserver(Observer o);
public synchronized int countObservers();
public void notifyObservers();
public synchronized void notifyObservers(Object arg);
public synchronized void deleteObservers();
protected synchronized void setChanged();
protected synchronized void clearChanged();
protected synchronized boolean hasChanged();
}
Listing 3.TextFieldView.java,theConcreteObserverfor theApplicationexample.
/*
** TextFieldView.java
**
** A ConcreteObserver
**
*/
import java.awt.TextField;
import java.util.Observer;
import java.util.Observable;
class TextFieldView extends TextField implements Observer {
private Value value;
public void update(Observable o, Object arg) {
if(o instanceof Value){
value = (Value) o;
setText(Float.toString(value.getValue()));
  }
}
}
Listing 4. ThePanelViewclass.
/*
** PanelView.java
**
** Another ConcreteObserver for the Application example
**
*/
import java.awt.Panel;
import java.awt.Graphics;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Color;
import java.util.Observer;
import java.util.Observable;
class PanelView extends Panel implements Observer {
private Value value;
private int lastPercentage;
public void setlastPercentage( int _lastPercentage){lastPercentage = _lastPercentage;}
public int getlastPercentage( ){ return lastPercentage ;}
public void update(Observable o, Object arg) {
if(o instanceof Value){
Graphics g = getGraphics();
value = (Value)o;
setlastPercentage((int)value.getValue());
repaint();
  }
}
public void paint(Graphics g) {
Dimension d = size();
FontMetrics fm = g.getFontMetrics();
int textHeight = fm.getAscent() + fm.getDescent();
StringBuffer s = new StringBuffer();
s.append(getlastPercentage());
s.append("%");
g.setColor(Color.cyan);
g.fillRect(0, 0,
(int)(d.width * (getlastPercentage() / 100.0)),
d.height);
g.setColor(Color.black);
g.drawString(s.toString(),
(int)((d.width - fm.stringWidth(s.toString()))/2),
(int)((d.height - textHeight)/2 + fm.getAscent()));
}
}
This simple applet just creates the components and defines the relationships.
ConcreteObserver and ConcreteObservable are are
both created by the applet itself, and the Observer
is added to the notify list right here. In general, the applet itself does
not need to create all of the relationships. You can even have the constructor
for the Observer take
an Observable as a parameter,
although you will usually not want to introduce another class dependency.
By constructing the relationship outside of the two classes being related,
you reduce the coupling between those classes and allow them to be related
in different ways as the occasions arise.
Subject
does not know any concrete Observer, Subject
still knows that it is actually observed. It has an interface for attaching
observers and a communication protocol with them (notifyObservers).
On the other hand, observers not only know that they observe, but, even
worse, also whom they observe (they know the concrete Subject).
Still, they also have to obey the communication protocol (update()
method). Even if this approach leads to a robust design that can be
successfully reused, in terms of actual conceptual modelling it is not
a natural design, it does not promote component reuse, and can be problematic
when dealing with software evolution. setValue() in
class Value. Naturally, what this method is supposed to
do is just to set the value. However, in the case above,
it does more than that: it also sends notifications to the Observers,
a functionality clearly not natural for a method such as setValue().
Consider now the class Value. It declares itself as being
observable. Is this natural? Perhaps, if ConcreteSubject
was of a kind that we can assume will always be observed, for instance
a thermometer, then perhaps constructing ConcreteSubject
as observable is a natural design. But what if it is that case that
ConcreteObservable is something like a Stock class in a stock-trading
system? Is it always observable? If it is constructed as observable
why having all this extra code when it is not? Even worse, if it is
coded as not observable, how we can make it Observable? Clearly, by
modifying the code. In other words, add all these statements that are
necessary to implement an Observable class. But are such modifications
desirable from the evolution point of view? The answer is clearly no.
Consider now the observers. Is it natural for them to know that they
observe and whom they observe? Is it natural for the class TextFieldView
above, that is supposed to draw, to actually know by default
not only how but also what it draws? What if we wanted to reuse it for
drawing something different, not related to Value? The point we wish
to make is this: Even if there are better designs to deal with some
of these issues, for instance an Observer with a manager (mediator)
(see [1] ), they can not be so dynamic to support code reuse and software
evolution without having to make intrusive code modifications. The reason
is simple: we can not predict evolution at design time and therefore
we need a methodology and not just good designs in order to deal with
the dynamic nature of software evolution. PanelView to paint using one font and
another object to paint using another font? Clearly by either subclassing
PanelView or by adding another paint() operation.
But there are two problems with these solutions. In the first case we
make a static adaptation of PanelView. Subclassing is
static because a future removal from the domain or modification of the
asset that we wished to model by subclassing, can not be performed so
easily without triggering changes to other parts in which the (sub)class
participated. The second case is often even worse. Firstly, adding an
interface is not always possible. But even when it is, it is very likely
to be intrusive not only to the components in which it is added but
also to other parts of the system. We
still use the term Observable and Observer just to make a direct analogy
to the classes above, but in fact there are no more Observable and Observer.
Actually, with the contracts approach, all the code in orange in the above
classes in not needed. In other words, the components should originally
being built without the code in orange. The components provide what they
are supposed to provide. There is no Observable class, no Observer interface,
no notifyObservers(), no update(), no registration
of observers, no classes that observe and know what they observe. It is
the contracts that link the Subject (Observable) to other objects that are
interested in changes of the Subject state. In other words, any instance
of any class can either be an Observable or an Observer depending on the
kind of contracts you plug on top of it. Moreover, contracts are not mediators.
Actually, Subject and Observers do not even know that contracts exist. Contracts
are plugged on top of them, providing the ability to coordinate and superpose
the behaviour of the Observers based on the state changes on the Subject.
Consider the following contract, that can detect changes on the state of
Value and coordinate the behaviour of TextFieldView.
Listing 6. ValueTextFieldViewContract between Value and TextFieldView.
Subject is
private (internal to Subject)?SubjectInterface of the Component part of the contracts
pattern. Therefore, in order to use contracts instead of Observer, with
all the advantages discussed above, operations such as setValue()
should be public. Alternatively, you may use state condition rules to detect
changes of state and perform the necessary actions. Exercise 1.
set-name of attribute
that you can use at the contract configuration. Note that this contract
may be the implementation of a new requirement for drawing based on
your system time. Think how difficult it would be to implement this
using the initial Observer-design without "touching" your components
(subclassing,add interfaces,modify code etc).
paintInColor. Can you think of an altenative
design so that contracts share its code and you do not have to define
the operation twice? Hint: Create a class that defines the paintInColor
operation and have the class as a contract attribute. Remember to create
an instance of such a class in each contract. You may do that inside
an initialize() operation that is called by default in
the contract constructor.
For answers, please visit www.atxsoftware.com/CDE
© Copyright 2001 ATX Software SA. All rights reserved.