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

1. The 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. Links and Literature