Observer pattern revisited using Java 5 generics
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 deadly sin! 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? Sure, it has its 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 writer of theOnlineJobDatabase-class to subtypeJobDatabase, when he implementsObservable<JobDatabase>.)
But there’s also a great strength, which IMHO by far outweighs the said disadvantages:
- 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. ![]()
“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 writer of the OnlineJobDatabase-class to subtype JobDatabase, when he implements Observable.)”
Maybe I’m missing something, but is that desirable, anyway? Whether an Observable is itself a T or just forwards notifications for a T (or multiple T’s) shouldn’t matter to the outside world, should it? A notifier for T’s must not be itself a T. The “Favor composition over inheritance” rule comes to mind. The name “Observable” is a bit misleading then though, as the Observable implementor is not necessarily itself the observed object.
Also the attach/detach/notify implementations could be done generically in a class Notifier implements Observable
That’s a good point.
Is there a case where it may be desirable to put the notifying code into a different class than the Subject (in the GoF sense) class? I would think that the observed object itself is supposed to trigger notifications when it’s modified…
Speaking of doing a pre-implementation of attach/detach/notify; when you stick to the “composition over inheritance” rule, you’ll end up with something like the Cocoa NSNotificationCenter class. This classes concern is purely to keep a list of “observing”-relations and to dispatch notifications to observers. You can also tell it which method to call on each observer. Amazing stuff, but it probably doesn’t play too well with statically typed languages like Java…
I like the concept, but I’m having trouble grasping how you’re really going to avoid the equivalent of a bunch of ‘instance-ofs’ when you’re processing your observed events (assuming that Unemployed is also observing other producers such as ‘RecruiterSeminar’).
There are actually two answers to that question. The first is concerning the “instanceof” that I also refer to in the article (this could have been much more explicit though):
1. When just using the “Standard” Observer class that you can find in the Java class library, observers implement the interface method “void update(Observable o, Object arg)”. Even though a program may be designed so that a *specific* implementation only gets notifications from a *specific* Observable implementation, the type of the argument given in “update” is still “Observable”. Thus, a cast is needed to do something more specific, therefore most programmers would use instanceof to check whether that cast will work first. Using generics, the correct type is given directly to the update method and both the cast and this instanceof aren’t needed any more.
2. The second part of the answer is concerned with the case that the observers observe a larger class hierarchy and thus more actual types can be passed to update(). (You won’t like this answer.
) I believe this problem is completely independent of the observer pattern in that the question is actually “what to do when different things must be done for different subclasses”. The basic answer is: Starting from a switch statement or multiple if-constructs, move the code for the different cases into the relevant class hierarchy and use Polymorphism instead.
There are people who say that instanceof is generally to be avoided, and when working in an Object Oriented context, it probably makes sense. Here’s a bigger discussion on that topic:
http://c2.com/cgi/wiki?InstanceofInConditionals
http://c2.com/cgi/wiki?ReplaceConditionalWithPolymorphism
I hope I could help you a bit. If not, feel free to ask.
So what you’re doing really just bypasses the ‘instanceof/cast’. There’s still got the same underlying problem of only being able to observe one ‘class’ of object for an observable. I assume what you were saying in the 2nd part was that I could compose an object which could listen to the different classes from different producers.
I’m playing around with an application that listens to a controller- the controller needs to send messages, which I thought would be straightforward. But each message could have different components (from states to actual data), which mean different objects. So I guess I’m stuck with the ‘instanceof’ model. I guess an improvement would be if Observer could have method signatures with the desired class instead of passing ‘Object’. That’s an old beaten horse, since Observer/Observable have been around since 1.0.
Yes, it just bypasses the
instanceofand the cast. It’s also true that an observer can only observe one kind of class (plus subclasses) now. I also identified this in the article itself (the first bullet point), but the language is probably a bit too technical there.When you want to make you object both a subclass of
Observer<A>andObserver<B>(A and B being unrelated classes), it’s not possible in Java as far as I know. (This has to do with byte code compatibility to earlier versions where generics were not possible yet.) However, if the object in the Observer role registers itself at the observable object, it may be possible to use inner classes that implementObserver<A>andObserver<B>. (The inner classes’ instances can only be created by an instance of the surrounding class and can also access private methods and fields of that object.)Unfortunately, avoiding
instanceofis usually not straightforward. Here’s the bird view on that issue: When implementing some functionality in a method, you can usually choose into which class that method belongs. (For the other related objects, it may be unavoidable to useinstanceof.) A simple heuristic would be to identify of which of used argument objects (also the receiver object [1]) the most instance variables need to be used (or simply “which is the most important object in this piece of code?”). Another concern is that you usually want to be able to use polymorphism (so that subclasses can override methods), but it only works on the receiver argument. To choose, which of the used objects is the receiver, there needs to be some kind of imbalance between all the argument objects. However, in some cases, the imbalance is not always given and all argument objects are equally important. If that happens, I usually try the following:(1) Building an additional layer of abstraction around one or more of these arguments, so that they are used in a less direct way. As a result, an imbalance can be established, thereby marking the “most important” object’s class as the class, where the method fits into best. Another result of an additional layer of abstraction is often that the use of
) Java doesn’t support this as a language feature, but the visitor pattern does exactly that. (I just recently wrote a blog entry about it, where I talk about that pattern, but the best resource on the topic probably is the classic “Gang of Four” design patterns book. http://home.earthlink.net/~huston2/dp/visitor.html looks good, too. Be careful about the sources you use here, because many people see the visitor pattern very much from a “walking tree structures” angle, which is a very related idea that can be done easily using it, but which leads many people into the mistaken belief that this is all the pattern does.)
instanceof“moves into the implementation of that layer”. When applying this technique recursively, it ultimately usually disappears.(2) If this doesn’t work, you need something called “multiple dispatch”. This means that the question, which method is to be executed when a call is made, is answered not only using the type of the receiver object, but instead using the types of *all objects* handed as arguments. (Note that you can directly use this to avoid
instanceofs!To sum up, I have made the experience that (1)
instanceofusage often disappears by adding more layers of abstraction and (2) if this makes difficulties, the visitor pattern can be used as last escape.I’m afraid this may have been even more confusing than the previous comment I wrote. I hope it still helps. In doubt, don’t trust me but trust the Gang of Four book.
Also don’t take patterns too dogmatic. It’s not so important to use the exact same names as in the books, but if you know a pattern and you have thought about its advantages and disadvantages, it often helps to explore the design space faster or in a more efficient manner. If you have some new insights, I’d be happy to hear about it.
[1] Small example for terminology: In the following code snippet, “taxi” is the receiver object, “memphis” and “driver” are arguments to the method:
taxi.drive(driver, memphis);
When considering the order of these arguments, it makes sense to see all three “taxi”, “driver” and “memphis” as plain arguments first and later decide which of the classes Car, Person and City is imporant enough to host the “drive” method.