I've just received my copy of the Head First Design Patterns book. I'm loving it so far! But maybe (I am a java/OO newby) I've discovered an error in the book that's not presented in the errata at o'reilly's website. Please tell me if I'm right.
The error concerns the Code Magnets exercise on page 69. There is a code fragment "WeatherData weatherData = (WeatherData)observable;". In the answer on page 78 it says that that part should go into the constructor. However I would place it in the update() method like this:
If the part isn't inserted there then the weatherData.getPressure() call can't compile since is an weatherData unknown variable. And inserting it in the constructor seems of no use to me.
Well, the one problem I see with your code is in the use of instanceof, What happens if different types are passed to the update method, now you will have to have multiple if statements checking for instanceof, and that can get to be a maintenance and readability problem.
But I do agree that the weatherData variable would not be accessible outside of the constructor, if it is coded like you have said.
I got that compiler error too and think it might be a boo boo. If so, it will probably show up in the errata eventually.
I'm no expert on this stuff, but I assume that since this is the implementation of update() in the ForecastDisplay class, it probably doesn't care if another type of Observable is passed in. It's only interested in updating if it gets WeatherData. That's just how I understand it, so that and about 10 bucks will get you a cup of Starbuzz coffee.
Mark van de Veerdonk
Joined: Dec 08, 2004
Thanx! Always nice to see that other people have similar problems.
Mark, I understand the point you're making. However, I think that a listener should be subscribed to a single type of Observable. It may be subscribed to multiple instances of the same type of subject but to only one type. If the Observer argument can be of different types then there's no getting around the 'instanceof' usage in the update() method. Although another way is to completely ignore the observable parameter and use a class variable (initialized in the constructor or by a setter method) to retrieve updated data.
I just checked this out, and it *is* an error. Thank you for finding it! We will fix it for the next printing and post an errata.
Regarding the issue of having to check the type - this is definitely an issue! We considered long and hard whether to implement it this way, and decided in the end to do it. The idea is that an Observer can observe multiple Observables. The Observables could be of a variety of different types, in which case, you would have to either implement multiple update() methods, each with a different signature, or you have to check the type of the Observable so you know what methods to call. Either way, you have to update the Observer class every time you add a new Observerable type.
In practice, I have found that I rarely (if ever?? can't recall now) write Observers to observe multiple, differently typed Observers. Upon consideration now, I might write this code differently and just hardcode the type in the update() method's signature... but as always, it's a tradeoff.
If you're only ever going to be observing one Observable and the type won't change, then you don't even need to bother sending along the Observable (assuming you're not using Java's built-in Observable of course), and can just rely on the update() method getting a set of arguments that will always be the same.