The Observer Pattern
How one object tells many listeners that something happened without knowing who they are.
Open this lesson in the learning hubKey points
- The subject keeps a list of listeners and calls them all when something happens. It never names them.
- That is how you add email, metrics and a warehouse hook without touching the class that places orders.
- In modern Java a listener is usually a
Consumeror a small interface, registered with a lambda. - Listeners run on the caller thread by default, so one slow listener slows the whole publish. Hand off if that matters.
- A listener that throws will stop the rest unless you catch per listener. Decide which behaviour you want.
- Remember to unsubscribe. A listener list is a strong reference and it is a very common source of leaks.
Example
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
public class Main {
// The subject knows only that somebody wants to hear about this.
static class OrderBook {
private final List<Consumer<String>> listeners = new ArrayList<>();
void onPlaced(Consumer<String> listener) { listeners.add(listener); }
void place(String id) {
System.out.println("order " + id + " placed");
for (Consumer<String> listener : listeners) {
listener.accept(id); // publish to every subscriber
}
}
}
public static void main(String[] args) {
OrderBook orders = new OrderBook();
orders.onPlaced(id -> System.out.println(" email : receipt for " + id));
orders.onPlaced(id -> System.out.println(" warehouse : pick " + id));
orders.onPlaced(id -> System.out.println(" metrics : counted " + id));
orders.place("A-1");
orders.place("A-2");
System.out.println("OrderBook never mentions email, warehouse or metrics");
}
}
Publish to a list of listeners and the subject stops depending on its audience.
This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the OOP course, and every lesson in it is listed on the OOP contents page.