Observer Pattern in Java (with Example)
The Observer pattern explained: a subject notifies a list of observers automatically when its state changes — the pub/sub, event-listener, and MVC pattern. Push vs pull, Java code, UML, when to use.
🟢 Design Patterns · Behavioral · Fresher → 🟠senior
The Observer pattern sets up a one-to-many relationship: when one object changes, all its dependents are notified automatically. It's the pattern behind newsletter subscriptions, UI event listeners, and pub/sub systems — anywhere "when X happens, tell everyone who cares." Once you see it, you'll recognise it in nearly every event-driven system you use.
The problem
A WeatherStation's temperature changes, and several displays (phone app, website, billboard) must update. The naive approach hardcodes each display into the station — now the station knows about every display, and adding a new one means editing the station. Tight coupling, constant edits. You want the station to just announce "I changed!" and whoever's interested reacts.
The solution: subscribe & notify
🟠The subject keeps a list of observers and exposes subscribe()/unsubscribe(). On any change it loops through and calls update() on each — without knowing what they do:
interface Observer { void update(float temp); }
class WeatherStation { // the subject
private final List<Observer> observers = new ArrayList<>();
private float temp;
public void subscribe(Observer o){ observers.add(o); }
public void unsubscribe(Observer o){ observers.remove(o); }
public void setTemp(float t){
this.temp = t;
for (Observer o : observers) o.update(t); // notify everyone
}
}
class PhoneDisplay implements Observer {
public void update(float t){ System.out.println("Phone: " + t); }
}
// wire it up:
station.subscribe(new PhoneDisplay());
station.setTemp(25.5f); // all subscribers update automatically
The station only knows the Observer interface. Add a new display → it subscribes; no station changes. Displays can subscribe/unsubscribe at runtime. That's loose coupling between the source of a change and the reactions to it.
Push vs pull
🟠A design nuance: in push, the subject sends the data in update(temp) (simple, but sends everything). In pull, the subject just says "I changed" and observers call back to fetch what they need (more flexible when there's lots of state). Mentioning the push/pull choice is a nice senior detail.
Where you meet it
Observer is everywhere: GUI event listeners (a button's click listeners are observers), the publish/subscribe model in messaging systems, reactive streams (RxJava), model→view updates in MVC, and Java's PropertyChangeListener. Any "event listener," "callback," or "subscriber" is Observer in disguise.
A caution
🔴 Two gotchas seniors mention: notification order isn't guaranteed, so observers shouldn't depend on running in a particular sequence; and forgetting to unsubscribe a dead observer causes memory leaks (the subject keeps a reference to it). In long-lived systems, manage subscriptions carefully.
When to use it
Use Observer when a change to one object must automatically update an unknown/variable number of others, and you want them decoupled — event systems, notifications, live dashboards, model-view syncing. If there's exactly one fixed dependent, a direct call is simpler.
The interview-ready summary
"Observer creates a one-to-many link: a subject keeps a list of observers and calls update() on all of them when its state changes, so they react automatically. The subject only knows the Observer interface, so it's loosely coupled — new observers just subscribe, no subject edits. It underpins event listeners, pub/sub, and MVC. I'd note push-vs-pull for the data, and to unsubscribe dead observers to avoid leaks." That's Observer with the real-world nuances."
What to read next
- State Pattern — changing behaviour with internal state
- Message Queues & Kafka — pub/sub at system scale
- All Design Patterns (hub)
- ← The complete System Design guide (hub)