Observer Pattern
Define a one-to-many dependency between objects so that when one object (Subject) changes state, all its dependents (Observers) are notified and updated automatically.
Observer = YouTube subscriptions. The creator (subject) uploads a video, and every subscriber (observer) gets notified automatically. The creator has no idea who's watching — they just hit publish and the bell rings everywhere.
Subject maintains a list of Observers and calls notify() on state change. Observers register and deregister themselves. Classic Java: java.util.Observable (deprecated) and EventListener. Modern equivalent: event bus (Guava EventBus, Spring ApplicationEventPublisher), reactive streams (RxJava Observable, Project Reactor Flux). Observer enforces DIP: Subject depends on the Observer interface, not concrete observers.
Observer has several known failure modes: (1) Memory leaks — Subject holds strong references to Observer; if the Observer is not explicitly removed, it is never GC'd. Solution: use WeakReference or ensure explicit unsubscription lifecycle. (2) Lapsed listener problem — deregistered observer still holds a reference to the Subject. (3) Notification order — observers are called in registration order by default; order dependency between observers is a hidden coupling. (4) Cascading updates — observer A's update triggers B's update which triggers A's update — infinite loop. (5) Exception isolation — if observer A throws, observers B–N are not called. Reactive streams (Project Reactor, RxJava) solve most of these: backpressure, error channels, composable operators, and declarative subscription management.
Observer decouples the Subject from the logic that reacts to its changes. In an e-commerce order system: OrderService is the Subject; EmailNotifier, InventoryUpdater, and AnalyticsTracker are Observers. When an order completes, the service fires a single event and each observer handles it independently. I always raise two issues: memory leaks from forgotten listener deregistration, and exception isolation (wrap each notification in try/catch so one bad observer doesn't block the rest). For production, I'd use an event bus or message queue to get delivery guarantees and async processing.
Observer assumes synchronous in-process communication. If an observer does IO (sends email, writes to DB), the Subject blocks. For IO-heavy observers, use an async event bus or a message broker (Kafka, RabbitMQ). Do not conflate Observer (in-process, synchronous by default) with publish-subscribe (cross-process, async, broker-mediated).