In real systems, one object’s state often changes in ways that multiple other parts of the program need to react to. If the central object starts directly calling all of them, coupling grows quickly. The observer pattern is a classic way to make that notification flow looser.
In this post, we will cover:
- what the observer pattern is
- why it appears so often in change notification flows
- how it relates to publish-subscribe style thinking
- when it fits well
The key idea is that the observer pattern keeps the state owner and its listeners more loosely connected, so new reactions can be added with less disruption to the central object.
What is the observer pattern?
The observer pattern is a structure where one object notifies interested observers when its state changes.
In simple terms:
- there is a subject
- there are observers
- state changes trigger notifications
That is the basic flow.
Why is it useful?
Imagine an order status changes, and then multiple things may need to happen:
- send notifications
- write logs
- update statistics
- refresh UI state
If the order object directly knows and calls all of those actions, its responsibilities grow too much. The observer pattern helps reduce that tight coupling.
Is it the same as publish-subscribe?
It is very similar in spirit, though the implementation and scope can differ depending on the system.
For beginners, the important structural idea is:
- a change happens
- interested listeners react
When does it fit well?
- when state changes trigger multiple follow-up actions
- when the set of listeners may grow
- when the core logic should know less about downstream reactions
So it fits especially well in event-like flows with multiple responses.
Common misunderstandings
1. If notifications exist, you should always use observer
Not always. For very small and stable relationships, direct calls may be simpler.
2. The observer pattern is always asynchronous
No. It can be implemented synchronously or asynchronously.
3. Event-style code automatically means low coupling
If event flows become too numerous and opaque, understanding the system can become harder.
Simple Example
interface Observer {
update(status: string): void;
}
class EmailNotifier implements Observer {
update(status: string): void {
console.log(`Send email: ${status}`);
}
}
class SlackNotifier implements Observer {
update(status: string): void {
console.log(`Send Slack message: ${status}`);
}
}
class Order {
private observers: Observer[] = [];
subscribe(observer: Observer): void {
this.observers.push(observer);
}
changeStatus(status: string): void {
this.observers.forEach((observer) => observer.update(status));
}
}
const order = new Order();
order.subscribe(new EmailNotifier());
order.subscribe(new SlackNotifier());
order.changeStatus('PAID');
The key point is that Order only depends on the Observer contract. New reactions can be added without rewriting the central state owner.
FAQ
Q. Where should beginners consider observer first?
Think about it when one state change leads to many follow-up actions.
Q. Is it the same as a callback?
It overlaps a little, but the observer pattern focuses more on subscriber relationships around state changes.
Q. Does it help even in small projects?
Yes, especially once one event starts triggering several independent reactions.
Read Next
- For changing object connections in another way, compare it with the Adapter Pattern Guide.
- For adding behavior by wrapping objects, read the Decorator Pattern Guide.
While AdSense review is pending, related guides are shown instead of ads.
Start Here
Continue with the core guides that pull steady search traffic.
- Middleware Troubleshooting Guide: Redis vs RabbitMQ vs Kafka A practical middleware troubleshooting guide for developers covering when to reach for Redis, RabbitMQ, or Kafka symptoms first, and which problem patterns usually belong to each tool.
- Kubernetes CrashLoopBackOff: What to Check First A practical Kubernetes CrashLoopBackOff troubleshooting guide covering startup failures, probe issues, config mistakes, and what to inspect first.
- Kafka Consumer Lag Increasing: Troubleshooting Guide A practical Kafka consumer lag troubleshooting guide covering what lag usually means, which consumer metrics to check first, and how poll timing, processing speed, and fetch patterns affect lag.
- Kafka Rebalancing Too Often: Common Causes and Fixes A practical Kafka troubleshooting guide covering why consumer groups rebalance too often, what poll timing and group protocol settings matter, and how to stop rebalances from interrupting useful work.
- Docker Container Keeps Restarting: What to Check First A practical Docker restart-loop troubleshooting guide covering exit codes, command failures, environment mistakes, health checks, and what to inspect first.
While AdSense review is pending, related guides are shown instead of ads.