Last Updated: December 31, 2025
The Observer Design Pattern is a behavioral pattern that defines a one-to-many dependency between objects so that when one object (the subject) changes its state, all its dependents (observers) are automatically notified and updated.
This pattern shines in scenarios where:
A straightforward approach is to directly call update methods on other objects whenever something changes. For example, a NewsPublisher might call update() on a MobileApp, EmailService, and WebsiteFeed every time a new article is published.
But as the number of subscribers grows, this approach becomes rigid, hard to scale, and violates the Open/Closed Principle. Adding or removing subscribers requires modifying the publisher class. It also tightly couples the publisher to all its subscribers.
The Observer Pattern solves this by decoupling the subject and its observers, allowing them to interact through a common interface. Observers can be added or removed at runtime, and the subject doesn’t need to know who they are.
Let’s walk through a real-world example to see how we can apply the Observer Pattern to build a flexible, extensible, and loosely coupled notification system that’s perfect for event-driven applications.
Imagine you are building a Fitness Tracker App that connects to a wearable device. The device continuously streams real-time fitness data: steps taken, active minutes, and calories burned. This data flows into a central FitnessData object.

Now, multiple modules within your app need to react to these updates:
| Module | Responsibility |
|---|---|
| LiveActivityDisplay | Shows real-time stats on the dashboard |
| ProgressLogger | Persists data to a database for trend analysis |
| GoalNotifier | Sends alerts when the user hits milestones |
In a simple approach, the FitnessData object directly holds and manages references to all its dependent modules.
This works initially, but let us think about what happens as the application grows.
The FitnessData class now has intimate knowledge of every module that cares about its data. It holds direct references to LiveActivityDisplay, ProgressLogger, and NotificationService.
If any of these classes change their interface, or if you want to replace one with a different implementation, you must modify FitnessData.
What happens when you want to add a WeeklySummaryGenerator? Or a SocialSharingService that posts achievements to social media?
Each new feature requires you to:
FitnessDatanewFitnessDataPushed() methodThe class is open for modification when it should be closed.
Modules like the NotificationService or ProgressLogger can’t be added or removed at runtime. What if the user disables notifications in their settings?
You’ll need to add even more conditionals to manually enable/disable parts of the code — making things fragile and error-prone.
The FitnessData class should have one job: managing fitness metrics. Instead, it is now responsible for UI updates, database logging, and notification logic. This violates the Single Responsibility Principle and makes the class difficult to test in isolation.
As the number of dependents grows, newFitnessDataPushed() becomes a lengthy sequence of method calls, each potentially with different parameters and error handling requirements. The method becomes a bottleneck that every developer must understand and modify.
We need a better, scalable way to solve this problem, something that allows:
FitnessData to broadcast changes to multiple listeners, without knowing who they areThis is exactly what the Observer pattern provides.
The Observer Design Pattern provides a clean and flexible solution to the problem of broadcasting changes from one central object (the Subject) to many dependent objects (the Observers) — all while keeping them loosely coupled.
In our Fitness Tracker App, the Observer Pattern allows the FitnessData object to notify all registered modules (like LiveActivityDisplay, ProgressLogger, and GoalNotifier) automatically whenever new fitness data is received — without needing to know what those modules are or how they respond.
FitnessDataObserver)update() method.update() to respond to updates.FitnessDataSubject)Declares methods to:
registerObserver() – subscribe to updatesremoveObserver() – unsubscribe from updatesnotifyObservers() – notify all current observers of a changeThe subject doesn't care who the observers are — it just sends updates.
FitnessData)FitnessDataSubject.FitnessDataObserver objects.notifyObservers() to broadcast the change.LiveActivityDisplay)FitnessDataObserver interface.update() is called, each observer pulls relevant data from the subject and performs its own logic (e.g., update UI, log progress, send alerts).Let’s refactor our fitness tracker system using the Observer Pattern.
FitnessDataObserver InterfaceEach observer receives a reference to the subject and can pull whatever data it needs. This keeps the interface stable even as FitnessData evolves.
FitnessDataSubject InterfaceThis interface allows observers to register and unregister themselves, and lets the subject notify all observers of changes.
FitnessData Class (ConcreteSubject)This class will hold the actual fitness data, manage a list of observers, and notify them upon data changes.
Each observer defines its own update() logic based on the new fitness data.
Now we wire everything together and simulate some fitness updates:
FitnessData doesn’t care who is listening — it just broadcastsWeeklySummaryGenerator) only requires implementing FitnessDataObserver — no changes to FitnessData