Evaluating Software Design Patterns
— the "Gang of Four" patterns implemented in Java 6

@Pattern(name="Observer", scope=Object, purpose=Behavioural, participants={"Subject","ConcreteSubject","Observer","ConcreteObserver"})

Package dk.rode.thesis.observer

Implementations and examples of the Observer design pattern [Gamma95, p.293].

See:
          Description

Interface Summary
AspectObservable<O,A> An aspect observable object is an object that has a collection of associated observers to be notified in case the object changes its internal state, or aspect, and where the observers can subscribe certain aspects only.
AspectObservableSequence<O,A,E> An aspect observable sequence is a sequence that allows for observers of the type supplied as the type parameter O to subscribe to specific sequence aspect values and be notified when the sequence changes its aspect to such a value.
Observable<O> An observable object is an object that has a collection of associated observers to be notified in case the object changes its internal state, or aspect.
ObservableSequence<O,A,E> An observable sequence is a sequence that allows for observers of the type supplied as the type parameter O to be notified when the sequence changes its aspect.
SequenceObserver<A> A sequence observer is an object that is notified when the observable sequence it is attached to changes its aspect value.
 

Class Summary
AnnotatedObserversSequence<E> An annotated observers sequence implements the basic traits of any observable sequence that uses the Executor annotation to identify notification methods for observers that accepts a Sequence type as the first argument and a Sequence.State type as the second.
AnnotatedObserversSequenceDecorator<E> An annotated observers sequence decorator decorates any Sequence to become an observable sequence that uses the Executor annotation to identify notification methods for observers that accepts a Sequence type as the first argument and a Sequence.State type as the second.
BirthdayRegistry A birthday registry is a simple application that stores the name and date of birth of people registered to it.
CorrelatedSequenceObserver A correlated sequence observer correlates the behaviour of an observable sequence with another (perhaps observable) Sequence.
DateSequence An observable date sequence is a sequence that will advance an initial date by one day each time next() is invoked and then notify relevant observers of its state changes.
Main Observer tests.
ObserverManager An observer manager is a stand-alone manager storing any type of observer that will be notified with methods declared in its class that are annotated with a matching Executor annotation.
PrintSequenceObserver A print sequence observer prints the state of any observable sequence it is observing.
ProbeSequenceObserver A probe sequence observer prints the internal attributes that has changed for a given sequence since the last time the observer was notified about that sequence, based on equality using equals(Object) (and hashCode()).
SequenceObserversSequence<E,A> A sequence observers sequence implements the basic traits of any observable sequence that uses a sequence observer as the notification mechanism.
SequenceObserversSequenceDecorator<E,A> A sequence observers sequence decorator decorates any sequence to become an observable sequence that uses a sequence observer as the notification mechanism.
 

Enum Summary
ObserverManager.NotificationPolicy Default error handlers for observer registries.
 

Package dk.rode.thesis.observer Description

Implementations and examples of the Observer design pattern [Gamma95, p.293].

Intent:

Here, the Subject participant is represented by the Observable interface. The Observable interface only defines methods for adding, removing, and fetching observers, but no a method to notify the observers. The type of observers must also be specified by a type parameter. All this is left up to the actual implementations, because different implementations will have different needs to the type of notification performed, for example in the type of arguments used, the notification order, asynchronous notification, etc. The AspectObservable type extends Observable to allow observers to subscribe to specific aspects only.

A refinement of the Observable interface is the ObservableSequence type, which represents a Sequence that will notify observers when its internal aspect changes, typically when its internal state has changed. The AspectObservableSequence sub-type allows observers to sub-scribe to specific aspects only, i.e. to specific internal state values only.

For observable sequences, the Observer participant is partly represented by the SequenceObserver interface, which defines the notification method to use. As a feature, ObserverableSequence extends SequenceObserver, and thus uses the inherited notification method to notify its observers. If the actual ObservableSequence at the same time chooses to use SequenceObserver as the observer type, the notification method is used to both issue and receive notifications. This makes the observable composite.

However, observers need not be related to sequences, nor be required to use the SequenceObserver interface. As an alternative, any object annotated with the Executor annotation may be considered a representative of the Observer participant under certain conditions (see implementation notes below).

Two abstract sub-classes of the ObservableSequence interface have been defined as well, also representing the Subject participant, namely the SequenceObserversSequence and AnnotatedObserversSequence classes. The first represents an observable sequence that uses SequenceObserver types as observers, while the latter represents an observable sequence that uses annotated objects as observers.

The ConcreteSubject participant is represented by any non-abstract implementation of the Observable interface. The DateSequence class is an observable sequence inheriting SequenceObserversSequence, while the ObserverManager class is a stand-alone observer manager storing annotated objects as observers; it is not specifically related to sequences and the changed subjects are supplied as arguments to the notification method (Change Manager). A specific implementation of the AnnotatedObserversSequence class have been made in form of the AnnotatedObserversSequenceDecorator class that can be used to make any sequence observable using annotated objects as observers.

The CorrelatedSequenceObserver, PrintSequenceObserver, ProbeSequenceObserver, and BirthdayRegistry classes all represent the ConcreteObserver participant. All except ProbeSequenceObserver implements the SequenceObserver interface. The latter uses annotations and so does the PrintSequenceObserver class. The PrintSequenceObserver can thus be used as an observer for both abstract sub-classes of ObserverableSequence.

UML Class Diagram:

Implementation notes:
The AnnotatedObserversSequence class internally uses a ObserverManager via object composition. Annotated observers works by annotating one or more methods in a given observer class - regardless of visibility, name, and if static - with the Executor annotation. However, the formal parameter types of the methods must match those supplied at construction time to the AnnotatedObserversSequence instance used (and thus to the ObserverManager used). At notification time, corresponding arguments must then supplied to the notification method that reflectively will invoke each annotated method.

The BirthdayRegistry class uses an inner class to implement the observer functionality, which ensures that we do not expose the SequenceObserver interface for misuse. This is common practice in Java. However, since the inner class is in effect an adapter, the exact type of notification mechanism used by the observable sequence must be known. For the birthday registry, the SequenceObserver interface is used, and this limits the type of applicable observable sequences to SequenceObserver<SequenceObserver,Date>.

As a curiosity, Java provides the java.util.Observable and java.util.Observer classes to support the Observer pattern, and has done so since version 1.0 or so. To our knowledge, these classes are rarely used. The interface they provide seems far from adequate, and most methods are synchronised. Internally a java.util.Vector is even used, practically deprecated since version 1.2!

Author:
Gunni Rode / rode.dk

Gunni Rode / rode.dk

Feel free to use and/or modify the Java 6 source code developed for this thesis AT YOUR OWN RISK, but note that the source code comes WITHOUT ANY — and I do mean WITHOUT ANY — form of warranty WHAT SO EVER!

The original thesis and source code are available at rode.dk/thesis.