Java > Design Patterns in Java > Behavioral Patterns > Observer Pattern
Observer Pattern Implementation in Java
The Observer pattern is a behavioral design pattern that 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. This example demonstrates a simple implementation of the Observer pattern in Java.
Conceptual Overview
The Observer pattern involves two key roles: the Subject and the Observer. The Subject maintains a list of Observers, and notifies them of state changes. Observers register with the Subject to receive these notifications. This pattern promotes loose coupling, as the Subject doesn't need to know the specific details of each Observer; it only knows that they implement the Observer interface.
Subject Interface (Observable)
This interface defines the contract for any object that wants to be observable. It includes methods to register, remove, and notify observers.
import java.util.ArrayList;
import java.util.List;
interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
Observer Interface
This interface defines the contract for any object that wants to observe a Subject. It includes an update method that is called when the Subject's state changes.
interface Observer {
void update(String message);
}
Concrete Subject (NewsPublisher)
This class implements the Subject interface. It maintains a list of observers and notifies them when the news is updated. The `setNews` method triggers the notification process.
class NewsPublisher implements Subject {
private List<Observer> observers = new ArrayList<>();
private String news;
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(news);
}
}
public void setNews(String news) {
this.news = news;
notifyObservers();
}
}
Concrete Observer (NewsSubscriber)
This class implements the Observer interface. It receives updates from the Subject and prints them to the console.
class NewsSubscriber implements Observer {
private String name;
public NewsSubscriber(String name) {
this.name = name;
}
@Override
public void update(String news) {
System.out.println(name + ": Received news: " + news);
}
}
Client Code (Main)
This class demonstrates how to use the Observer pattern. It creates a Subject (NewsPublisher) and two Observers (NewsSubscribers). It registers the observers with the subject, sets the news, and then removes one of the observers before setting the news again.
public class Main {
public static void main(String[] args) {
NewsPublisher publisher = new NewsPublisher();
NewsSubscriber subscriber1 = new NewsSubscriber("Alice");
NewsSubscriber subscriber2 = new NewsSubscriber("Bob");
publisher.registerObserver(subscriber1);
publisher.registerObserver(subscriber2);
publisher.setNews("Breaking news: Java 21 released!");
publisher.removeObserver(subscriber1);
publisher.setNews("Another news: Spring Framework update.");
}
}
Real-Life Use Case
A common real-life use case is in GUI frameworks where UI elements (Observers) need to be updated when the underlying data (Subject) changes. For example, a spreadsheet application uses the Observer pattern: when a cell's value changes, dependent charts and calculations are automatically updated.
When to use them
Use the Observer pattern when:
Best Practices
Alternatives
Alternatives to the Observer pattern include:
Pros
Cons
FAQ
-
What is the difference between Observer and Publish-Subscribe?
The Observer pattern is typically implemented directly between subjects and observers, while Publish-Subscribe uses a message broker or event bus as an intermediary. Publish-Subscribe offers greater decoupling. -
How can I avoid memory leaks in the Observer pattern?
Use weak references to observers, or ensure that observers are properly unregistered from the subject when they are no longer needed. -
Is the Observer pattern suitable for multithreaded environments?
Yes, but you need to ensure thread safety by using synchronization mechanisms to protect the observer list and notification process.