When implementing the Observer pattern, there are two main approaches to consider: the 'push' model and the 'pull' model.
In the 'push' model, the subject (i.e. the Observable) sends the observer on notification all the data it will need. The observer doesn't need to query the subject for information. In the 'pull' model, the subject merely notifies the observer that something happaned, and the observer queries the subject based to get the information it needs.
Let's discuss the pros and cons of both approaches:
The main advantage of the 'push' model is lower coupling between the observer and the subject. The observer doesn't need to know anything about the subject in order to query it. If it needed to, we'd need to do one of the following: A- do downcasting on the side of the observer in order to invoke class-specific
get methods on the subject. This is bad. B- make the
Observable interface more class-specific, offering specific
get methods, thus making the relationship between the observer and subject less general and making things more copupled.
By implementing the 'push' model, we avoid all of this.
However the disadvantage is less flexibility: the subject may not always know what exact information the observers need in order to send it to them. This will often mean more specific Observer intefaces, such as
AgeObserver that are notified when the 'age' of the subject is changed, and
HeightObserver which are sent the current
height of the subject on notification.
This is one option. The other is the subject sending a whole lot of information encapsulated in an
Info object of some sort and have the observers query it from there. But again, we can't be sure we're sending the correct info. So it's either this, or forcing the observers to implement more specific Observer interfaces, which tightens the coupling on the observer's side.
I already noted the disadvantages of the 'pull' model. The observers would have to know things about the subject in order to query the right information, which leads A- to downcasting (ugly), or B- favorably to more specific
Observable interfaces, that offer more specific accessor methods. For example
AgeObservable offers a
The advantage of this is more flexibility. Each observer can decide for itself what to query, without relying on the subject to send the correct information.
You should choose the strategy that is better for the specific project you're working on.
In reality, you'll always have specific
Observable intefaces, so you have some coupling between the sides anyway.
So choose either 'pull' or 'push' by what fits you best.
AgeObservers need simply the
age of the subject? Implement the 'push' model. Less coupling and simpler.
HeightObservers need varying information about the subject - aka one needs to query the age too, and some other object needs to query the weight in addition to the height? Implement the 'pull' model. This would force you to add accessors (getters) to the
Observable inteface (either this or pass the actual object as a parameter in it's explicit type, but doing this through the interface allows you to deny the observers access to things that don't matter to them). This soultion creates higher coupling, but it's more flexible.
Choose what fits your situation best.