Support free tutorials









vogella training Training Books



Observer Design Pattern in Java - Tutorial

Lars Vogel

Version 1.5

22.05.2013

Observer

This article describes the Observer design pattern and its usage in the programming language Java.


Table of Contents

1. Observer Pattern
1.1. Definition
1.2. Example
1.3. Code example
1.4. Evaluation
2. Support this website
2.1. Thank you
2.2. Questions and Discussion
3. Links and Literature

1. Observer Pattern

1.1. Definition

The observer pattern defines a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified and updated automatically.

The object which is being watched is called the subject. The objects which are watching the state changes are called observers or listeners.

1.2. Example

The observer pattern is very common in Java. For example, you can define a listener for a button in a user interface. If the button is selected, the listener is notified and performs a certain action.

But the observer pattern is not limited to single user interface components. For example, you could have a part A in your application which displays the current temperature.

Another part B displays a green light if the temperature is above 20 degree celsius. To react to changes in the temperature, part B registers itself as a listener to Part A.

If the temperature in part A is changed, an event is triggered. This event is sent to all registered listeners, as, for example, part B. Part B receives the changed data and can adjust its display.

The following example code shows such a listener implementation for a button.

Button button =  new Button(shell, SWT.PUSH);

//register listener for the selection event
button.addSelectionListener(new SelectionAdapter() {
  @Override
  public void widgetSelected(SelectionEvent e) {
    System.out.println("Called!");
  }
}); 

1.3. Code example

In the following example the observer is watching changes in a List of People objects. For this example create a new Java project called com.vogella.java.designpattern.observer and the following classes.

package com.vogella.java.designpattern.observer;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;

public class MyModel {
  public static final String FIRSTNAME = "firstName";
  public static final String LASTNAME = "lastName";

  private List<Person> persons = new ArrayList<Person>();
  private List<PropertyChangeListener> listener = new ArrayList<PropertyChangeListener>();

  public class Person {

    private String firstName;

    private String lastName;

    public Person(String firstName, String lastName) {
      this.firstName = firstName;
      this.lastName = lastName;
    }

    public String getFirstName() {

      return firstName;
    }

    public void setFirstName(String firstName) {
      notifyListeners(this, 
          FIRSTNAME,
          this.firstName, 
          this.firstName = firstName);
      
    }

    public String getLastName() {
      return lastName;
    }

    public void setLastName(String lastName) {
      notifyListeners(this, 
          LASTNAME, 
          this.lastName, 
          this.lastName = lastName);
    }
  }

  public List<Person> getPersons() {
    return persons;
  }

  public MyModel() {
    // just for testing we hard-code the persons here:
    persons.add(new Person("Lars", "Vogel"));
    persons.add(new Person("Jim", "Knopf"));
  }

  private void notifyListeners(Object object, String property, String oldValue, String newValue) {
    for (PropertyChangeListener name : listener) {
      name.propertyChange(new PropertyChangeEvent(this, property, oldValue, newValue));
    }
  }

  public void addChangeListener(PropertyChangeListener newListener) {
    listener.add(newListener);
  }

} 

package com.vogella.java.designpattern.observer;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

public class MyObserver implements PropertyChangeListener {
  public MyObserver(MyModel model) {
    model.addChangeListener(this);
  }

  @Override
  public void propertyChange(PropertyChangeEvent event) {
    System.out.println("Changed property: " + event.getPropertyName() + " [old -> "
      + event.getOldValue() + "] | [new -> " + event.getNewValue() +"]");
  }
} 

package com.vogella.java.designpattern.observer;

import com.vogella.java.designpattern.observer.MyModel.Person;

public class Main {

  public static void main(String[] args) {
    MyModel model = new MyModel();
    MyObserver observer = new MyObserver(model);
    // we change the last name of the person, observer will get notified
    for (Person person : model.getPersons()) {
      person.setLastName(person.getLastName() + "1");
    }
    // we change the name of the person, observer will get notified
    for (Person person : model.getPersons()) {
      person.setFirstName(person.getFirstName() + "1");
    }
  }
} 

1.4. Evaluation

The observer pattern allows for the Open Closed principle. This principle states that a class should be open for extensions without the need to change the class.

Using the observer pattern a subject can register an unlimited number of observers. If a new listener wants to register with the subject, no code change in the subject is necessary.

Using the listener pattern decouples the subject from its observers. Only the observers have direct knowledge about the subject.

2. Support this website

This tutorial is Open Content under the CC BY-NC-SA 3.0 DE license. Source code in this tutorial is distributed under the Eclipse Public License. See the vogella License page for details on the terms of reuse.

Writing and updating these tutorials is a lot of work. If this free community service was helpful, you can support the cause by giving a tip as well as reporting typos and factual errors.

2.1. Thank you

Please consider a contribution if this article helped you. It will help to maintain our content and our Open Source activities.

2.2. Questions and Discussion

If you find errors in this tutorial, please notify me (see the top of the page). Please note that due to the high volume of feedback I receive, I cannot answer questions to your implementation. Ensure you have read the vogella FAQ as I don't respond to questions already answered there.

3. Links and Literature

Wikipedia Entry about the GOF Design Pattern book.