środa, 29 grudnia 2010

Type safe Observer/Observable

Using generic design pattern in statically typed languages can lead to some problems related to type safety. For instance let's take a look at the implementation of Observer design pattern in Java which has been created in the pre generics era.
It consists of two classes namely Observer and Observable and in simplified form looks like this:

public interface Observer {
    void update(Observable observable);
}

public class Observable {
    public void addObserver(Observer observer) { }
    public void notifyObservers() { }
}

Let's assume that we want to have two distinct subclasses of Observer and Observable. ObserverA can observe instances of ObservableA only and ObserverB can observe instances of ObservableB only.


How should we define all those classes to enforce correct behaviour? As simple as this question seems to be the solution might not be as obvious for people who don't know generics too much.
The solution is to parametrize both Observer and Observable with two type parameters one for Observer subclass and the other one for Observable subclass.

public interface Observer<T extends Observer<T,O>, 
    O extends Observable<O,T>> {
    void update(O observable);
}

public class Observable<T extends Observable<T,O>, 
    O extends Observer<O,T>> {
    public void addObserver(O observer) { }
    public void notifyObservers() { }
}

public interface ObserverA extends 
    Observable<ObserverA, ObservableA> {
}

public class ObservableA extends 
    <ObservableA, ObserverA > {
}

Thanks to this ObserverA.update() will accept subclasses of ObservableA only and ObservableA.addObserver() will accept subclasses of ObserverA.
The same solution can be applied to any set of classes which depend on each other. In this context simply parametrize each of them with one type parameter for each of the classes.

1 komentarz: