Observer Pattern
IntermediateObserver defines a one-to-many dependency so that when one object changes state, all dependents are notified automatically.
Overview
The Observer pattern (also known as publish-subscribe or event listener) decouples the subject (publisher) from its observers (subscribers). The subject maintains a list of observers and notifies them when state changes. Java's built-in support includes java.util.Observable (deprecated), PropertyChangeListener, and the more modern event bus libraries. Spring's ApplicationEventPublisher and RxJava are modern Observer implementations.
Classic Observer Implementation
Define an Observer interface with an update method. The Subject maintains a list of observers and calls update() on all of them when relevant state changes. Observers register and deregister dynamically.
This is the pattern behind Swing event listeners, Android onClick listeners, and most GUI frameworks.
import java.util.*;
// Observer interface
public interface StockObserver {
void onPriceChange(String symbol, double newPrice);
}
// Subject
public class StockTicker {
private final Map<String, Double> prices = new HashMap<>();
private final List<StockObserver> observers = new ArrayList<>();
public void subscribe(StockObserver observer) {
observers.add(observer);
}
public void unsubscribe(StockObserver observer) {
observers.remove(observer);
}
public void updatePrice(String symbol, double price) {
prices.put(symbol, price);
notifyObservers(symbol, price);
}
private void notifyObservers(String symbol, double price) {
for (StockObserver observer : observers) {
observer.onPriceChange(symbol, price);
}
}
}
// Concrete observers
StockTicker ticker = new StockTicker();
ticker.subscribe((sym, price) ->
System.out.printf("Alert: %s hit %.2f%n", sym, price));
ticker.subscribe((sym, price) ->
System.out.printf("Log: %s = %.2f%n", sym, price));
ticker.updatePrice("AAPL", 185.50);PropertyChangeListener (Java Standard Library)
java.beans.PropertyChangeSupport is the standard library Observer implementation for JavaBeans. It fires PropertyChangeEvent when a property changes, carrying old and new values.
This is used in JavaFX properties, Swing components, and any Bean that needs change notification.
import java.beans.*;
public class User {
private final PropertyChangeSupport pcs =
new PropertyChangeSupport(this);
private String name;
private int age;
public void addPropertyChangeListener(PropertyChangeListener l) {
pcs.addPropertyChangeListener(l);
}
public void removePropertyChangeListener(PropertyChangeListener l) {
pcs.removePropertyChangeListener(l);
}
public void setName(String newName) {
String old = this.name;
this.name = newName;
pcs.firePropertyChange("name", old, newName);
}
public void setAge(int newAge) {
int old = this.age;
this.age = newAge;
pcs.firePropertyChange("age", old, newAge);
}
}
User user = new User();
user.addPropertyChangeListener(evt ->
System.out.printf("Property '%s' changed: %s → %s%n",
evt.getPropertyName(), evt.getOldValue(), evt.getNewValue()));
user.setName("Alice"); // fires eventSpring ApplicationEvents
Spring provides a built-in Observer mechanism via ApplicationEventPublisher. Publish custom events with publishEvent(); listen with @EventListener or implementing ApplicationListener.
This is the recommended Observer implementation in Spring applications — no manual listener lists.
// Event class
public class OrderPlacedEvent {
private final String orderId;
private final String customerId;
public OrderPlacedEvent(String orderId, String customerId) {
this.orderId = orderId;
this.customerId = customerId;
}
public String getOrderId() { return orderId; }
public String getCustomerId() { return customerId; }
}
// Publisher
@Service
public class OrderService {
@Autowired
private ApplicationEventPublisher publisher;
public Order placeOrder(OrderRequest req) {
Order order = processOrder(req);
publisher.publishEvent(
new OrderPlacedEvent(order.getId(), req.getCustomerId()));
return order;
}
}
// Listener
@Component
public class EmailNotificationListener {
@EventListener
public void onOrderPlaced(OrderPlacedEvent event) {
sendConfirmationEmail(event.getCustomerId(), event.getOrderId());
}
}Key Points to Remember
- Observer decouples subjects from observers — neither knows the concrete type of the other.
- Subject holds a list of Observer references; calls update() on each when state changes.
- Java standard library: PropertyChangeSupport, Swing listeners, JavaFX properties.
- Spring: ApplicationEventPublisher + @EventListener is the idiomatic Observer.
- Be careful of memory leaks — unregister observers when no longer needed.
Practice Observer Pattern in the Playground
Run and modify code directly in your browser - no setup needed.
Interview Questions
Sign in to ask AriaWhat is the difference between Observer and Pub/Sub patterns?
How do you prevent memory leaks in the Observer pattern?
How does Spring's @EventListener relate to the Observer pattern?
What is the difference between synchronous and asynchronous event notification?
Why was java.util.Observable deprecated in Java 9?
Ask Aria about Observer Pattern
Your personal AI tutor — ask anything about this concept