Observer Pattern – Using the Pulling Mechanism in Java

javaobserver-pattern

I was wondering about the following implementation of

public void update(Observable obs, Object arg)

while I want to send to all of my observer and update using notifyObserver() I and passing a references to this the observer can use the getters from the subject to pull the information he wants.

What is the arg argument on the update method meant for?

Best Answer

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:

Push

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.

Pull

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 getAge() method.

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 Observer and Observable intefaces, so you have some coupling between the sides anyway.

So choose either 'pull' or 'push' by what fits you best.

Do all AgeObservers need simply the age of the subject? Implement the 'push' model. Less coupling and simpler.

Do all 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.

Related Topic