Java Observer Pattern

By Paulus, 6 August, 2010

The best way to think about the Observer Design pattern is to think of it as "You are observing something. When what you are watching does something, you react to it."  This is also sometimes called a publish-subscribe relationship. The comments in the story help put what's going on in perspective. The interfaces aren't necessary.

  1. Crate an interface for the subject, subject being a lion in this case:
    /**
     * Basic functions of a subject.
     *
     * @author paulus
     */
    public interface Subject {
    
      public void addObserver( Observer ob );
    
      public void removeObserver( Observer ob );
    
    }
  2. Next we need to define an observer interface:
    /**
     * Basic functions of an observer.
     *
     * @author paulus
     */
    public interface Observer {
      /*
       * Also called "update"
       */
      public void see( Subject sub );
    }
  3. We're going to implement the interface for a lion class:
    import java.util.*;
    
    /**
     * The type of subject observers will see.
     *
     * @author paulus
     */
    public class Lion implements Subject {
      /*
       * List of everyone who is watching.
       */
      private ArrayList observers = new ArrayList();
    
      /*
       * What the lion is eating.
       */
      private String animal;
      /*
       * The action those who are watching can see.
       */
      public void eat( String str ) {
        this.animal = str;
        showObservers();
      }
    
      /*
       * What the lion is eating.
       */
      public String meal() {
        return animal;
      }
    
      /*
       * Function to add "people" to watch this object.
       */
      public void addObserver( Observer o ) {
        observers.add(o);
      }
    
      /*
       * Function for "people" to walk away and stop watching this object.
       */
      public void removeObserver( Observer o ) {
        observers.remove(o);
      }
    
      /*
       * Show the observers that the lion is eating an animal.
       */
      private void showObservers() {
        Iterator i = observers.iterator();
        while(i.hasNext()) {
          Observer o = (Observer) i.next();
          o.see(this);
        }
      }
    }

    The observers ArrayList variable is a listing of everyone who is watching the lion while the string called animal is simplely what the lion is currently eating. When the function eat is called, we're taking the argument passed and showing it to the observers variable, or everyone who is watching that particular lion. At any time people can look away or watch; this is achieved by the addObserver or removeObserver functions.

  4. We're going to implement the observer interface for a Person class:
    /**
     * Type of observer
     *
     * @author paulus
     */
    public class Person implements Observer {
    
      /*
       * Name of observer
       */
      private String name;
    
      /*
       * Specific lion this person is observing.
       */
      private Lion lion;
    
      /*
       * This person's name is, and which lion he is watching.
       */
      public Person( String name, Lion subject ) {
        this.lion = subject;
        this.name = name;
        lion.addObserver(this);
      }
    
      /*
       * See the the lion eat an animal.
       */
      public void see(Subject s) {
        if( s == lion ) {
          System.out.println(name + " just saw the lion just eat a(n) " + lion.meal() + "!");
        }
      }
    }
  5. We're going to set up an environment where people can go to see the lions eat:
    /**
     *
     * @author paulus
     */
    public class Zoo {
    
      public static void main(String[] args) {
    
        /*
         * There are seen on this safari
         */
        Lion first_lion = new Lion();
        Lion second_lion = new Lion();
    
        /*
         * These are the people that are on the safari.
         */
        Person paul = new Person("Paul", first_lion);
        Person jim = new Person("Jim", second_lion);
        Person carie = new Person("Carie", first_lion);
    
        /*
         * Paul and Cari see the first lion eat a zebra.
         */
        first_lion.eat("zebra");
        /*
         * Cari looks away
         */
        System.out.println("Carie looks away!");
        first_lion.removeObserver(carie);
        /*
         * the lion has an elephant for desert.
         */
        first_lion.eat("elephant");
    
        /*
         * Paul sees a second lion, Jim also sees it too.
         * This lion eats a sheep.
         */
        second_lion.addObserver(paul);
        second_lion.eat("sheep");
      }
    }