Observer Design Pattern

According to the GoF definition, the observer pattern defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically. It is also referred to as the publish-subscribe pattern. In the observer pattern, many observers (subscriber objects) observe a …

Observer Pattern

According to the GoF definition, the observer pattern defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically. It is also referred to as the publish-subscribe pattern.

In the observer pattern, many observers (subscriber objects) observe a particular subject (publisher object). Observers register with a subject to be notified when a change is made inside that subject.

An observer object can register or unregister from a subject at any point in time. This helps make the objects loosely coupled.

1. When to use the Observer design pattern?

As described above, the observer pattern can be used when designing a system where multiple entities are interested in any possible update to some particular second entity object.

Observer Pattern

The flow is very simple to understand. The application creates the concrete subject instance. All concrete observers register to be notified of further updates in the subject’s state.

As soon as the state of the subject changes, the subject notifies all the registered observers, and the observers can access the updated state and act accordingly.

Observer Pattern Sequence Diagram
Observer Pattern Sequence Diagram

2. Real-world Examples of Observer pattern

  • Any social media platform, such as Facebook or Twitter, can be a real-world example of an observer pattern. When a person updates his status, all his followers get a notification. A follower can follow or unfollow another person at any point in time. Once unfollowed, a person will not get notifications from the subject in the future.
  • In programming, the observer pattern is the basis of message-oriented applications. When an application has updated its state, it notifies the subscribers about updates. Frameworks like HornetQ and JMS work on this pattern.
  • Similarly, in Java UI-based programming, all keyboard and mouse events are handled by listener objects and designated functions. When a user clicks the mouse, a function subscribed to the mouse click event is invoked with all the context data passed to it as a method argument.

3. How to Implement Observer Design Pattern?

Let’s see how to implement the observer pattern in a Java application.

3.1. Architecture

The following diagram defines a one-to-many dependency between objects so that when one object (the subject) changes state, all its dependents (observers) are notified and updated automatically.

Observer Pattern Architecture
Observer Pattern Architecture

3.2. Design participants

The observer pattern has four participants.

  • Subjectinterface or abstract class defining the operations for attaching and de-attaching observers to the subject.
  • ConcreteSubject – is a concrete Subject class. It maintains the state of the object and notifies the attached observers when a change in the state occurs.
  • Observer – interface or abstract class defining the operations to notify this object.
  • ConcreteObserver – concrete Observer implementations.

4. Observer Pattern In Action

In the below example, I am creating a message publisher of type Subject and three subscribers of type Observer. The publisher will publish the message periodically to all subscribed or attached observers, and they will print the updated message to the console.

4.1. Subject and Concrete Subject

public interface Subject {

    public void attach(Observer o);
    public void detach(Observer o);
    public void notifyUpdate(Message m);
}
import java.util.ArrayList;
import java.util.List;

public class MessagePublisher implements Subject {

    private List<Observer> observers = new ArrayList<>();

    @Override
    public void attach(Observer o) {
        observers.add(o);
    }

    @Override
    public void detach(Observer o) {
        observers.remove(o);
    }

    @Override
    public void notifyUpdate(Message m) {
        for(Observer o: observers) {
            o.update(m);
        }
    }
}

4.2. Observer and Concrete Observers

public interface Observer {

    public void update(Message m);
}
public class MessageSubscriberOne implements Observer {

    @Override
    public void update(Message m) {
        System.out.println("MessageSubscriberOne :: " + m.getMessageContent());
    }
}
public class MessageSubscriberTwo implements Observer {

    @Override
    public void update(Message m) {
        System.out.println("MessageSubscriberTwo :: " + m.getMessageContent());
    }
}
public class MessageSubscriberThree implements Observer {

    @Override
    public void update(Message m) {
        System.out.println("MessageSubscriberThree :: " + m.getMessageContent());
    }
}

4.3. State Object

This must be an immutable object so that no class can modify its content by mistake.

public class Message {

    final String messageContent;

    public Message (String m) {
        this.messageContent = m;
    }

    public String getMessageContent() {
        return messageContent;
    }
}

4.4. Example

Now, test the communication between the publisher and subscribers.

public class Main {

	public static void main(String[] args) {

		MessageSubscriberOne s1 = new MessageSubscriberOne();
		MessageSubscriberTwo s2 = new MessageSubscriberTwo();
		MessageSubscriberThree s3 = new MessageSubscriberThree();

		MessagePublisher p = new MessagePublisher();

		p.attach(s1);
		p.attach(s2);

		p.notifyUpdate(new Message("First Message"));   //s1 and s2 will receive the update

		p.detach(s1);
		p.attach(s3);

		p.notifyUpdate(new Message("Second Message")); //s2 and s3 will receive the update
	}
}

Program output.

MessageSubscriberOne :: First Message
MessageSubscriberTwo :: First Message

MessageSubscriberTwo :: Second Message
MessageSubscriberThree :: Second Message

5. FAQs

5.1. Can different types of observers register to one subject?

The nature and functionality of observers can be different, but they all must implement one common Observer interface which the subject support for registering and deregistering.

5.2. Can I add or remove observers at runtime?

Yes. We can add or remove the observers at any point of time.

5.3. What is the difference between the observer and chain of responsibility patterns?

In an observer pattern, all registered handler objects receive notifications at the same time and process the update at the same time.

However, in a chain of responsibility pattern, handler objects are notified individually, and this process continues until one object fully handles the notification.

5.4. Benefits of the observer pattern?

The subject and observers make a loosely coupled system. They do not need to know each other explicitly. We can independently add or remove observers at any time.

Related Java classes:

Observer Java Doc
Observable Java Doc

Weekly Newsletter

Stay Up-to-Date with Our Weekly Updates. Right into Your Inbox.

Comments

Subscribe
Notify of
2 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.