Using the Observable/Observer pattern

An Observable object is an object that contains data in which one or more Observer objects are interested in.
The Observers want to know when the state of the Observable object changes.

The implementation is simple. In the package java.util, you find the class Observable. The object that you want to be able to monitor should extend from it. For example, suppose we have a Mailbox object (that can only contain one email at a time) and we know that other objects may be interested in state changes:

import java.util.*;
 
class Mailbox extends Observable
{
   private String message;
 
   public void newMail(String message) {
      this.message = message;
      setChanged();
      notifyObservers();
   }   
 
   public String getMessage() {
      return message;
   }
}

Observable is a class that encapsulates the common details about the pattern, like being able to “register” an object that is interested. Whenever the method newMail is invoked, the state changes and the object is marked as being changed. A call to notifyObservers means to notify the Observer objects that have previously registered themselves through addObserver, a method inherited from Observable.

An Observer is an interface that all your observers need to implement to ensure the availability and accessibility of the method update(Observable obs, Object o).

In our example, suppose we have two observers to our Mailbox: a MailGui and MailLog.

class MailGui implements Observer
{
   public void update(Observable obs, Object o) {
      Mailbox mb = (Mailbox) obs;
      System.out.println("MailGui has received notification of new " +
                         "message: " + mb.getMessage());
   }
}
 
class MailLog implements Observer
{
   public void update(Observable obs, Object o) {
      Mailbox mb = (Mailbox) obs;
      System.out.println("MailLog has received notification of new " +
                         "message: " + mb.getMessage());
   }
}

The notifyObservers method in Observable will loop through a list of objects of type Observer and calls the method update sequentially on each one of them. It provides itself as the first parameter (so the Observer knows which Observable we’re talking about – it may have registered itself with different ones) and an optional object as a second parameter. This optional object comes from when you call the notifyObservers(Object o) variant.

Here’s the Main class:

import java.util.*;
 
public class Main {   
   public static void main(String[] args) {
      Mailbox mb = new Mailbox();
 
      MailGui gui = new MailGui();
      MailLog log = new MailLog();
 
      mb.addObserver(gui);
      mb.addObserver(log);
 
      mb.newMail("... email#1 ...");
      mb.newMail("... email#2 ...");
   }
}

and the output:

MailLog has received notification of new message: ... email#1 ...
MailGui has received notification of new message: ... email#1 ...
MailLog has received notification of new message: ... email#2 ...
MailGui has received notification of new message: ... email#2 ...

Decoupling

It is important to realize that when an Observable wants to notify Observers of a change through calling update on them, it is tighly coupled to it. If update decides to go do some calculations, surf the net or play SkateOrDie, all actions that take forever to complete, the Observable cannot go on notifying other interested Observers cause it happens all in the same thread.

To perform some decoupling, you should place some threaded FIFO datastructure in between the Observable and Observer. The FIFO object would then both be an Observable and Observer.
Before:

                 (update)
  [ Observer1 ] <--------- [            ]
  [ Observer2 ] <--------- [ Observable ]
  [ Observer3 ] <--------- [            ] 

After:

                 (update)
  [ Observer1 ] <--------- [                 ]  (update)
  [ Observer2 ] <--------- [ FIFO Observable ] <--------- [ Observable ]
  [ Observer3 ] <--------- [                 ]