import java.util.WeakHashMap; import java.util.List; import java.util.LinkedList; import java.util.Iterator; /** * Defines the general behavior of the observer design pattern. * * Each concrete sub-aspect of ObserverProtocol defines one kind of observing * relationship. Within that kind of relationship, there can be any number * of subjects, each with any number of observers. * * The sub-aspect defines three things:
Subject
s and
* Observer
s. For each subject, a LinkedList
* is of its observers is stored.
*/
private WeakHashMap perSubjectObservers;
/**
* Returns a Collection
of the observers of
* a particular subject. Used internally.
*
* @param s the subject for which to return the observers
* @return a Collection
of s's observers
*/
protected List getObservers(Subject s) {
if (perSubjectObservers == null) {
perSubjectObservers = new WeakHashMap();
}
List observers = (List)perSubjectObservers.get(s);
if ( observers == null ) {
observers = new LinkedList();
perSubjectObservers.put(s, observers);
}
return observers;
}
/**
* Adds an observer to a subject. This is the equivalent of
* attach(), but is a method on the pattern aspect, not the subject.
*
* @param s the subject to attach a new observer to
* @param o the new observer to attach
*/
public void addObserver(Subject s, Observer o) {
getObservers(s).add(o);
}
/**
* Removes an observer from a subject. This is the equivalent of
* detach(), but is a method on the pattern aspect, not the subject.
*
* @param s the subject to remove the observer from
* @param o the observer to remove
*/
public void removeObserver(Subject s, Observer o) {
getObservers(s).remove(o);
}
/**
* The join points after which to do the update.
* It replaces the normally scattered calls to notify(). To be
* concretized by sub-aspects.
*/
protected abstract pointcut subjectChange(Subject s);
/**
* Call updateObserver after a change of interest to update each observer.
*
* @param s the subject on which the change occured
*/
after(Subject s): subjectChange(s) {
Iterator iter = getObservers(s).iterator();
while ( iter.hasNext() ) {
updateObserver(s, ((Observer)iter.next()));
}
}
/**
* Defines how each Observer
is to be updated when a change
* to a Subject
occurs. To be concretized by sub-aspects.
*
* @param s the subject on which a change of interest occured
* @param o the observer to be notifed of the change
*/
protected abstract void updateObserver(Subject s, Observer o);
}