Observer Pattern Tutorial with Java Examples
Learn the Observer Design Pattern with easy Java source code examples as James Sugrue continues his design patterns tutorial series, Design Patterns Uncovered
Join the DZone community and get the full member experience.
Join For FreeDesign patterns are one of the most valuable tools for developers. They illustrate the best design solutions that others have encountered, and allow you to apply the same principle to your own designs. More importantly, knowing design patterns gives a common vocabulary for software developers to use when talking about their designs.
In this article series, I'll be going through each pattern and describing how it's used and where it's applied in the real world. To start off, I'll be describing one of the most used design patterns, the Observer pattern.
Design Patterns Refcard
For a great overview of the most popular design patterns, DZone's Design Patterns Refcard is the best place to start.
The Observer In The Real World
Before we get into the theory and code behind the Observer, let's take a look at a real world example, such as RSS feeds. When I want to get updates from a particular feed, I add it to my feed reader. Any time that the RSS feed has an update, it will appear in my reader automatically. This is the Observer pattern in action, a publisher/subscriber relationship with one source having many subscribers.
The Observer Pattern
Of all of the design patterns that are out there, the Observer is one that you've probably used already, even if you weren't aware of it. The Observer pattern is the gold standard in decoupling - the seperation of objects that depend on each other.
The Observer is known as a behavioural pattern, as it's used to form relationships between objects at runtime. The definition provided in the original Gang of Four book on Design Patterns states:
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:
The idea behind the pattern is simple - one of 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 that the Observer may be interested in, 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 detatch themselves. The following sequence diagram illustrates the registration and notification flow in action.
The benefits here are quite clear. 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.
Where Would I Use This Pattern?
In general, you want to use this pattern to reduce coupling. If you have an object that needs to share it's state with others, without knowing who those objects are, the Observer is exactly what you need.
You'll have seen, and probably used, the Observer many times if you've done any UI programming, especially in Swing. The whole concept of listeners is based on this pattern. The event listener is the most popular, where you register an ActionListener to a UI control, such a button, and react to action events using the actionPerformed method. In this case, the ActionListener is the Observer and the button is your Subject. As the button changes state, you can react, if you choose to, in your actionPerformed method.
The typical real world uses of the pattern all revolve around this type of event handling system.
So How Does It Work In Java?
While some patterns require you to define the interfaces that make the pattern work, the Observer is a case where Java has the work done for you already in the java.util package.
The slight difference from the classic definition is that Observable is used in place of the Subject and is implemented as a class, while the Observer interface remains the same. Let's take a look at an implementation of the pattern with a real example. 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 {
@Overridepublic
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();
As you can see it's a really simple pattern to understand, and even easier to use thanks to the Java implementation of the pattern.
Watch Out for the Downsides
As with any piece of code, you need to be careful how you use the Observer pattern. Martin Fowler has a good list of gotchas for the observer. In his article he mentions that 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.
Enjoy the Whole "Design Patterns Uncovered" Series:
Creational Patterns
- Learn The Abstract Factory Pattern
- Learn The Builder Pattern
- Learn The Factory Method Pattern
- Learn The Prototype Pattern
Structural Patterns
- Learn The Adapter Pattern
- Learn The Bridge Pattern
- Learn The Decorator Pattern
- Learn The Facade Pattern
- Learn The Proxy Pattern
Behavioral Patterns
- Learn The Chain of Responsibility Pattern
- Learn The Command Pattern
- Learn The Interpreter Pattern
- Learn The Iterator Pattern
- Learn The Mediator Pattern
- Learn The Memento Pattern
- Learn The Observer Pattern
- Learn The State Pattern
- Learn The Strategy Pattern
- Learn The Template Method Pattern
- Learn The Visitor Pattern
Opinions expressed by DZone contributors are their own.
Comments