Observer Pattern — Implementation in Java
By: Anjana Shankar
Tags: Java, Design Patterns, Observer Design Pattern

What is an Observer Pattern?

Observer Pattern is one of the most commonly used design patterns. It is useful when you are interested in getting notified of the state changes of an object. It defines a one-to-many relationship between the subject and the observers.

Terminologies

Observer or Listener or Subscriber

The objects which are interested in knowing about the changes to another object are called as observers or listeners. Subject or Publisher

The object that is under observation is called Subject.

Pros

It is a typical Publisher — Subscriber model. Thus providing a loose coupling between the dependent objects. The Publisher does not have to know anything about the subscribers.

Cons

The publisher may send updates to the subscriber that don’t matter to the subscriber anymore.

UML diagram

Java Implementation

The subject will implement 3 methods.

RegisterObserver — This method will be called by the observer to register themselves. UnregisterObserver — This method will be called by the observer to unregister themselves. NotifyObserver — This method is called to notify the observers of any changes to the subject.

Let’s look at an example.

You have a list of friends. If your friend publishes a status, you would like to be notified of it. This is a typical use case of Observer pattern.

You register yourself as an observer to your friend’s status. When your friend publishes a status, the notify method is called, which will then call your update method.

Let us write the code for implementing Observer Pattern in Java.

Subject/Observer Interface

First let us define the two interfaces, subject and observer. They can be though of as Publisher and Subscriber as well.

public interface Subject {

public void register(Observer o);

public void unregister(Observer o);

public void notifyObservers();

}

Note that the subject has to implement the three methods register, unregister and notifyObserver as discussed in the above section.

public interface Observer {

public void update(String message);

}

Observer defines an Update method that is called from the notifyObservers method.

ConcreteSubject implements Subject

Let us look at the concrete implementations of the subject interface defined above.

public class ConcreteSubject1 implements Subject{



List<Observer> observers;

String message;



public ConcreteSubject1() {

this.observers = new ArrayList<>();

}



public String getMessage() {

return message;

}



public void setMessage(String message) {

this.message = message;

this.notifyObservers();

}



@Override

public void register(Observer o) {

observers.add(o);

}



@Override

public void unregister(Observer o) {

observers.remove(o);

}



@Override

public void notifyObservers() {

for(Observer o : observers) {

o.update(getMessage());

}

}

}

ConcreteObserver implements Observer

We define two concrete observer classes. Each implements the update method of the Observer interface.

public class ConcreteObserver1 implements Observer {

@Override

public void update(String message) {

System.out.println("Observer 1 received message - "+message);

}

} public class ConcreteObserver2 implements Observer {



@Override

public void update(String message) {

System.out.println("Observer 2 received message - "+message);

}

}

Main class

Bringing it all together.

public class Main {

public static void main(String[] args) {

ConcreteObserver1 observer1 = new ConcreteObserver1();

ConcreteObserver2 observer2 = new ConcreteObserver2();



ConcreteSubject1 subject1 = new ConcreteSubject1();

subject1.register(observer1);

subject1.register(observer2);



subject1.setMessage("Status change 1");



subject1.unregister(observer1);

subject1.setMessage("Status change 2");

}

}

The output is as follows. We register two observers to the subject. When the message gets updated the first time, both the observers are notified. After that we unregister the first observer. When the message gets updated again, we have only the second observer that gets notified.

Observer 1 received message - Status change 1

Observer 2 received message - Status change 1

Observer 2 received message - Status change 2

You can find the complete code on github.

Observer Pattern in Java Library

Java provided Observer Interface and Observable class. The Observer interface had to be implemented by the observers. The Observable class is similar to the Subject class in our implementation. These have been deprecated since Java9.

Oracle docs now suggest using java.beans package for implementing the Observer pattern.

Thread Safety

The implementation we have done is not thread safe. For a thread safe implementation, we can use the data structures in java.util.concurrent package.

The CopyOnWriteArrayList can be used for keeping the list of observers. This will be inefficient if the observers list is being frequently updated.

Reference: https://docs.oracle.com/javase/10/docs/api/java/util/Observable.html