Understanding Observer Patterns

The Observer design pattern lets several observer objects be notified when a subject object is changed in some way. Each observer registers with the subject, and when a change occurs, the subject notifies them all. Each of the observers is notified in parallel (that is, at the same time).

Creating a subject interface

When you implement a design pattern, it's often a good idea to start by creating an interface to make sure that the objects you create will adhere to the pattern you're trying to use — especially if multiple objects are involved. Implementing that interface — programming to an interface as it's called — keeps your code in line and usually keeps things clearer.

When you're putting the Observer pattern into code, set up an interface or abstract class for the observers; you'll usually have multiple observers, and you have to keep the methods they implement consistent.

In this example, you also need to set up an interface for the subject, which is what the observers watch; the Subject interface lists the methods subjects must implement. Put a registerObserver method here so that the subject can keep track of observers that want to be registered. Besides registering observers, you should have some way to get rid of them, so add a removeObserver method. And there's a notifyObservers method that will notify the observers of some change.

public interface Subject
{
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObservers();
}

This interface lists the methods that subjects like the database system should implement. Next up: the interface for the observers.

Creating an observer interface

Building the Observer interface, implemented by the observers to enable them to get notifications, is simple. All you need is a method that will be called when a new notification is ready (you can call that method update). In this example, you pass the database operation that was performed (such as "edit", "delete", "create" and so on) and the record that was changed as strings to the update method.

public interface Observer
{
public void update(String operation, String record);
}

When observers implement the update method, the subject is able to pass them the record that's been affected and the operation that was performed.

Okay, you're good to go. It's time to create the Database subject that is going to keep track of the observers and notify them when there's been a change.

Creating a subject

The subject has to let observers register and has to notify them when an event occurs. According to the Subject interface, the three methods a subject has to implement in these examples are: registerObserver, removeObserver, and notifyObservers. That's what the Database class does in this example.

To keep track of the observers, use a Java vector named observers, created in the Database constructor. (The type specifier here, <Observer>, is for Java 1.5 or later and indicates that each observer object implements the Observer interface; if you're using an earlier version of Java, omit the type specifier.)

import java.util.*;
public class Database implements Subject
{
private Vector<Observer> observers;

public Database()
{
observers = new Vector<Observer>();
}
.
.
.
}

When you use a vector, keeping track of observers is simple. When an observer wants to register, it calls the subject's registerObserver method, passing itself as an object. The subject — an object of our Database class — just has to add that observer to the observers vector in the registerObserver method, using the Vector class's add method.

import java.util.*;
public class Database implements Subject
{
private Vector<Observer> observers;

public Database()
{
observers = new Vector<Observer>();
}

public void registerObserver(Observer o)
{
observers.add(o);
}
.
.
.
}

How about removing an observer from the observers vector? No problem. When you want to remove an object from a vector, you can use the vector's remove method; here's how that works in the Database class's removeObserver method:

import java.util.*;
public class Database implements Subject
{
private Vector<Observer> observers;

public Database()
{
observers = new Vector<Observer>();
}

public void registerObserver(Observer o)
{
observers.add(o);
}

public void removeObserver(Observer o)
{
observers.remove(o);
}
.
.
.
}

When the user actually does something with the database — deletes a record, for example — he calls the Database class's editRecord method. For example, to delete record 1, you might call this method like this:

database.editRecord("delete", "record 1");

Here's what the editRecord method looks like: When this method is called, you pass it the database operation you want to perform and the record you want to work on, both as strings in this example. Those strings are stored so they can be passed on to the observers. After the strings are stored, the notifyObservers method, coming up next, is called to notify all observers.

import java.util.*;
public class Database implements Subject
{
private Vector<Observer> observers;
private String operation;
private String record;

public Database()
{
observers = new Vector<Observer>();
}
.
.
.
public void editRecord(String operation, String record)
{
this.operation = operation;
this.record = record;
notifyObservers();
}
}

Here's the meat of the code, the part that notifies each observer that there's been a change: the notifyObservers method. Each observer implements this example's Observer interface — which means it has an update method — so notifyObservers just has to loop over all registered observers in the observers vector, calling each one's update method with the database operation and affected record.

import java.util.*;
public class Database implements Subject
{
private Vector<Observer> observers;
private String operation;
private String record;
.
.
.
public void notifyObservers()
{
for (int loopIndex = 0; loopIndex < observers.size(); loopIndex++) {
Observer observer = (Observer)observers.get(loopIndex);
observer.update(operation, record);
}
}

public void editRecord(String operation, String record)
{
this.operation = operation;
this.record = record;
notifyObservers();
}
}

That's all you need for Database.java, the subject in this example. The subject will let observers register themselves, unregister themselves, and get notified when a database record has been edited (which you do with the Database class's editRecord method). All that's left to do to get this show on the road is to create the observers themselves.

  • Add a Comment
  • Print
  • Share
blog comments powered by Disqus
Advertisement

Inside Dummies.com

Dummies.com Sweepstakes

Win $500. Easy.