Java Observer Pattern
In this page:
Subject and Observer Interfaces
The Observer Pattern defines a one-to-many dependency between objects: when one object, the Subject, changes state, every one of its registered dependents, the Observers, is notified automatically without the Subject needing to know anything specific about them.
Example: Subject and Observer Interfaces
public class Main {
interface Observer { void update(String data); }
interface Subject {
void attach(Observer o);
void notifyObservers(String data);
}
public static void main(String[] args) {
System.out.println("Subject notifies every registered Observer automatically");
}
}
Login to try C/C++/Java/PHP code in the editor
Concrete Subject Implementation
A Concrete Subject tracks its observers in an internal list, exposing methods to attach or detach observers dynamically. When its state changes, it iterates through that list and calls each observer's update method to notify them.
Example: Concrete Subject Implementation
import java.util.*;
public class Main {
interface Observer { void update(String data); }
static class NewsPublisher {
List<Observer> observers = new ArrayList<>();
void attach(Observer o) { observers.add(o); }
void publish(String data) {
for (Observer o : observers) o.update(data);
}
}
public static void main(String[] args) {
NewsPublisher publisher = new NewsPublisher();
publisher.attach(data -> System.out.println("Received: " + data));
publisher.publish("Breaking news");
}
}
Login to try C/C++/Java/PHP code in the editor
Concrete Observer Implementation
A Concrete Observer implements the update method that the Subject calls into. Inside that method, it runs whatever custom logic is appropriate given the new data it just received, entirely independent of how the other observers respond to the same notification.
Example: Concrete Observer Implementation
public class Main {
interface Observer { void update(String data); }
static class LoggingObserver implements Observer {
public void update(String data) {
System.out.println("Logged: " + data); // independent of other observers
}
}
public static void main(String[] args) {
Observer observer = new LoggingObserver();
observer.update("event occurred");
}
}
Login to try C/C++/Java/PHP code in the editor
Dynamic Subscriptions
Observers can subscribe or unsubscribe from a Subject dynamically at runtime, not just at setup. This flexibility prevents memory leaks from observers that should have been removed, and ensures each observer only ever receives the specific events it's actually interested in.
Example: Dynamic Subscriptions
import java.util.*;
public class Main {
interface Observer { void update(String data); }
static class Subject {
List<Observer> observers = new ArrayList<>();
void attach(Observer o) { observers.add(o); }
void detach(Observer o) { observers.remove(o); }
void notifyEach(String data) { for (Observer o : observers) o.update(data); }
}
public static void main(String[] args) {
Subject subject = new Subject();
Observer o = data -> System.out.println("Got: " + data);
subject.attach(o);
subject.detach(o); // unsubscribed before the next notification
subject.notifyEach("no listeners left");
}
}
Login to try C/C++/Java/PHP code in the editor
Java Built-in Alternatives
Modern Java code commonly implements this pattern with custom, purpose-built listener interfaces rather than reaching for the JDK's original built-in Observer/Observable classes, which have been deprecated since Java 9 due to design limitations like lacking proper event ordering guarantees.
Example: Java Built-in Alternatives
public class Main {
interface ChangeListener { void onChange(String value); } // custom listener, not java.util.Observable (deprecated since Java 9)
public static void main(String[] args) {
ChangeListener listener = value -> System.out.println("Changed to: " + value);
listener.onChange("new state");
}
}
Login to try C/C++/Java/PHP code in the editor
Chapter Quiz — Complete all 14 topics to unlock
0/14 topics done
Complete these topics first:
- Java Design Patterns Introduction
- Java Singleton Pattern
- Java Factory Pattern
- Java Observer Pattern
- Java Builder Pattern
- Java MVC Architecture
- Java Adapter Pattern
- Java Decorator Pattern
- Java Strategy Pattern
- Java Command Pattern
- Java Facade Pattern
- Java Proxy Pattern
- Java Template Method Pattern
- Java Repository Pattern