Back to top

vogella training Training Books

Observer Design Pattern in Java

Lars Vogel

Version 1.5

22.05.2013

Revision History
Revision 0.1 01.07.2009 Lars
Vogel
created
Revision 0.2 - 1.5 22.05.2013 Lars
Vogel
bugfixes and update

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. Thank you
3. Questions and Discussion
4. 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);
button.addSelectionListener(new SelectionAdapter() {
  @Override
  public void widgetSelected(SelectionEvent e) {
    // Handle the selection event
    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 {

    private List<Person> persons = new ArrayList<Person>();
    private List<PropertyChangeListener> listeners = 
            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", 
                    firstName, 
                    this.firstName = firstName);
            // Remark 
          // this.firstName = firstName sends out the
          // set the field and send out the new value

            // Longer version:
            // String oldName = this.firstName;
            // notifyListeners(this, "firstName", 
            //  oldName, firstName);    
        }

        public String getLastName() {
            return lastName;
        }

        public void setLastName(String lastName) {
            notifyListeners(this, "lastName", 
                    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"));
        persons.add(new Person("Miguel", "Olave"));
    }

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

    public void addChangeListener(PropertyChangeListener newListener) {
        listeners.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. Thank you

Thank you for practicing with this tutorial.

3. Questions and Discussion

Before posting questions, please see the vogella FAQ. If you have questions or find an error in this article please use the www.vogella.com Google Group. I have created a short list how to create good questions which might also help you.

4. Links and Literature

http://en.wikipedia.org/wiki/Design_Patterns Wikipedia Entry about the GOF Design Pattern book.