โ Back to Design Patterns
๐๏ธ
Behavioral
Observer
Defines a one-to-many dependency so that when one object changes state, all its dependents are notified automatically.
The Problem
Multiple parts of an app need to react when some shared data changes, but you don't want the data source to be aware of or tightly coupled to its consumers.
How It Works
- โบSubject (publisher) maintains a list of observers (subscribers)
- โบLoose coupling: subject does not know concrete observer classes
- โบPush model sends data with the notification; pull model lets observers fetch it
- โบRisk of memory leaks if observers are not unsubscribed (use weak references)
- โบAlso known as Publish/Subscribe or Event Listener pattern
When to Use
โUI that must update when underlying data changes (data binding)
โEvent systems where multiple components react to the same event
โNotification systems, analytics tracking, logging across multiple targets
โReactive programming foundations (Combine, RxSwift, LiveData)
Real-World Examples
๐
iOS
NotificationCenter, Combine Publisher/Subscriber, KVO, @Published + @ObservedObject
๐ค
Android
LiveData.observe(), StateFlow.collect(), RxJava Observable, EventBus
๐
Web
EventEmitter (Node.js), RxJS Observable, Vue reactivity, React useEffect
Code Examples
Swift
protocol StoreObserver: AnyObject {
func storeDidUpdate<T>(_ newValue: T)
}
class Store<T> {
private var observers = [WeakBox]()
var value: T { didSet { notify(value) } }
init(_ value: T) { self.value = value }
func subscribe(_ observer: StoreObserver) {
observers.append(WeakBox(observer))
}
private func notify(_ newValue: T) {
observers.forEach { $0.value?.storeDidUpdate(newValue) }
}
private class WeakBox {
weak var value: StoreObserver?
init(_ v: StoreObserver) { value = v }
}
}
class CounterLabel: StoreObserver {
func storeDidUpdate<T>(_ newValue: T) {
print("Label updated: \(newValue)")
}
}
let store = Store(0)
let label = CounterLabel()
store.subscribe(label)
store.value = 5 // "Label updated: 5"
store.value = 10 // "Label updated: 10"