Observers and Observables

The java.util.Observer interface and java.util.Observable class are relatively small utilities, but they provide a glimpse of a fundamental design pattern in Java. Observers and observables are part of the MVC (Model-View-Controller) framework. It is an abstraction that lets a number of client objects (the observers) be notified whenever a certain object or resource (the observable) changes in some way. We will see this pattern used extensively in Java's event mechanism, covered in s 16 through 19. Although these classes are not often used directly, it's worth looking at them to understand the pattern. The Observable object has a method an Observer calls to register its interest. When a change happens, the Observable sends a notification by calling a method in each of the Observers. The observers implement the Observer interface, which specifies that notification causes an Observer object's update( ) method to be called. In the following example, we create a MessageBoard object that holds a String message. MessageBoard extends Observable, from which it inherits the mechanism for registering observers (addObserver( )) and notifying observers (notifyObservers( )). To observe the MessageBoard, we have Student objects that implement the Observer interface so that they can be notified when the message changes:

 //file: MessageBoard.java
 import java.util.*;
  
 public class MessageBoard extends Observable {
 private String message;
  
 public String getMessage( ) {
 return message;
 }
 public void changeMessage( String message ) {
 this.message = message;
 setChanged( );
 notifyObservers( message );
 }
 public static void main( String [] args ) {
 MessageBoard board = new MessageBoard( );
 Student bob = new Student( );
 Student joe = new Student( );
 board.addObserver( bob );
 board.addObserver( joe );
 board.changeMessage("More Homework!");
 }
 } // end of class MessageBoard
  
 class Student implements Observer {
 public void update(Observable o, Object arg) {
 System.out.println( "Message board changed: " + arg );
 }
 }


Our MessageBoard object extends Observable, which provides a method called addObserver( ). Each Student object registers itself using this method and receives updates via its update( ) method. When a new message string is set using the MessageBoard's changeMessage( ) method, the Observable calls the setChanged( ) and notifyObservers( ) methods to notify the observers. notifyObservers( ) can take as an argument an Object to pass along as an indication of the change. This object, in this case, the String containing the new message, is passed to the observer's update( ) method, as its second argument. The first argument to update( ) is the Observable object itself. The main( ) method of MessageBoard creates a MessageBoard and registers two Student objects with it. Then it changes the message. When you run the code, you should see each Student object print the message as it is notified. You can imagine how you could implement the observer/observable relationship yourself using a List to hold the list of observers. In and beyond, we'll see that the Java AWT and Swing event model extends this design pattern to use strongly typed observables and observers, called events and event listeners. But for now, we turn our discussion of core utilities to another fundamental topic: I/O.

Comments