Observer pattern revisited using Java 5 generics
Update 2013: I wouldn't recommend this trick at all any more. It's
probably nicer than the Observer
interface that comes with Java,
but if the scenario allows it (and most do), you can just as well
write specialized observer interfaces, which are much easier to
read. Take the following text with a grain of salt. :)
When implementing the observer pattern in Java, I always end up
implementing the whole Observer
and (sometimes)
Observable
(Subject
for you GoF-fanatics)
interface again and again for each type that's supposed to be
observed. So there's a QuestionnaireObserver
interface
for the Questionnaire
class, a
QuestionSectionObserver
interface for the
QuestionSection
class and so on.
You ask why? Well, let's see what happens when I use the standard Java
implementations of Observer
and Observable
:
I end up checking the type of the Observable
each time
the update() method is called on the observer — using
instanceof
. Unnecessary to say that
this is considered a code smell by some people.
So let's take a look at what we have right now - thousands of classes doing the same stuff, just for different types... a case for the big refactoring book! - O rude unthankfulness!, the book covers Java 2 only! So what do we do?
Numerous web searches suggest I'm either the first to search for that problem or I'm too stupid to ask the right questions (which is way more likely in this case). :-) Consequently, I came up with my own solution. Let's use generics to remove that duplication:
Isn't this solution more elegant and reusable than the standard Observer-pattern classes in Java?
Weaknesses:
- We cannot implement an interface with parametric types twice:
There's no possibility to implement both
Observable<JobDatabase>
andObservable<Webpage>
at once. (Who wants that, anyway?) - I couldn't figure out how to restrict the generic type to be a
supertype of the class implementing the
Observer
/Observable
-interface. (Read: I cannot force the author of theOnlineJobDatabase
class to subtypeJobDatabase
, when he implementsObservable<JobDatabase>
.) </ul>
Strengths:
- No need to use
instanceof
, no need to cut&paste-program dozens ofObserver
-interfaces; and you can still get static type safety with this! :-)
And last but not least (although it was not easy), I even found evidence I'm not the only one using generics for this. :-)