Design Pattern: Observer Pattern

The Observer is known as a behavioural pattern, as it’s used to form relationships between objects at runtime.

Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

Let’s take a look at the classic diagram definition of  the observer:

One or more Observers are interested in the state of a Subject and register their interest with the Subject by attaching themselves. When something changes in our Subject, a notify message is sent, which calls the update method in each Observer.
When the Observer is no longer interested in the Subject’s state, they can simply detatchthemselves.

So How Does It Work In Java?

In our example, the subject will be a DataStore, with a Screen class as the observer.

First, let’s make our DataStore class observable by extending the java.util.Observable class. This means that our DataStore has all the methods and functionality available to make it a Subject, according to our pattern.

import java.util.Observable;

public class DataStore extends Observable
{
	
	private String data;
	
	public String getData()
	{
		return data;
	}
	
	public void setData(String data)
	{
		this.data =data;
		//mark the observable as changed
		setChanged();
	}	
}

 

You’ll notice that we have called the setChanged() method of the Observable. This is necessary in order for the call to notify observers to send out the update. Without this set, the Observable will see no reason to send out the update.

Next, let’s create our Observer. To do this, all we need to do is implement the Observer interface which forces us to write an update method, to deal with changes in the Observable’s state.

public class Screen implements Observer {

	@Override
	public void update(Observable o, Object arg) {

		//act on the update
	}

}

Adding our Screen as an observer to the DataStore is simple:

Screen screen = new Screen();

DataStore dataStore = new DataStore();
//register observer 
dataStore.addObserver(screen);

When the data changes, we want to notify all observers of this object. To do this, we just need to call the notifyObservers method when we want an update sent out

//send a notification
dataStore.notifyObservers();

Pros:

To pass data onto the observers, our subject doesn’t need to know who needs to know. Instead, everything is done through a common interface, and the notify method just calls all the objects out there that have registered their interest. This is a very powerful decoupling – meaning that any object can simply implement the Observer interface and get updates from the Subject.

Cons:

It can be difficult to see the path through the code, unless you are debugging. As such, you should be careful not to have chains of observers (observers acting as subjects). Also, watch out for memory leaks as the subject will hold a reference to the observer unless it has deregistered.

FacebookTwitterGoogle+Share

Leave a Reply

Your email address will not be published. Required fields are marked *