Skip to content

Latest commit

 

History

History
99 lines (67 loc) · 4.85 KB

File metadata and controls

99 lines (67 loc) · 4.85 KB

Real-World Applications of the Observer Pattern

1. Stock Price Alerts (this implementation)

A PriceTracker subject publishes price ticks for stock tickers. Observers (RetailInvestor, StopLossAlert, AuditLogger) each register with a custom ObservationHook that declares their interest condition — e.g. "only notify me when INFY drops below ₹1300". The subject evaluates each hook before dispatching, so observers only fire when their predicate is satisfied. This avoids polling and keeps each observer fully decoupled from the others.

2. Event Systems in UI Frameworks

Every frontend framework (React, Vue, Flutter) is built on Observer. A component subscribes to a state store; when state changes, the framework calls each subscriber to re-render:

type StateStore struct {
    observers []func(newState State)
    state     State
}

func (s *StateStore) Subscribe(fn func(State)) {
    s.observers = append(s.observers, fn)
}

func (s *StateStore) Dispatch(newState State) {
    s.state = newState
    for _, fn := range s.observers {
        fn(newState)
    }
}

Components never poll — they react. Adding a new component that depends on shared state is one Subscribe call.

3. Distributed Event Streaming (Kafka, NATS)

Kafka's consumer groups are Observer at scale. A topic (subject) retains messages; consumer groups (observers) each read the stream independently. Adding a new consumer — analytics pipeline, fraud detector, audit log — requires zero changes to the producer. This is Observer with a broker decoupling the two sides and enabling async, persistent fan-out.

4. Database Change Data Capture (CDC)

Databases like PostgreSQL emit row-level change events (insert, update, delete) via logical replication slots. Downstream services (search indexer, cache invalidator, audit trail) subscribe to the stream. Each reacts to changes without coupling to the service that wrote the row — a classic Observer topology with the WAL as the subject.

5. WebSocket / Server-Sent Event Subscriptions

A server maintains a registry of active WebSocket connections. When a backend event fires (new chat message, order status update, live score), the event handler iterates the registry and pushes to each connection:

type Hub struct {
    clients map[*Client]bool
}

func (h *Hub) Broadcast(msg []byte) {
    for client := range h.clients {
        client.send <- msg
    }
}

Clients connect and disconnect dynamically — the hub never knows what they do with the message, only that they implement the subscriber contract.

6. CI/CD Pipeline Status Notifications

A build system (GitHub Actions, Jenkins) notifies registered webhooks when a pipeline completes. Slack bots, deployment triggers, JIRA ticket updaters, and test reporters all subscribe to the same build event. Each webhook is an observer; the build system is the subject. Adding Datadog monitoring is one more webhook registration — no pipeline code changes.

7. Monitoring and Metrics Collection

Prometheus's scrape model inverts Observer (pull instead of push), but application-side metric collection is Observer: a metric registry (subject) emits snapshots; exporters (observers) format and forward them to different backends (Prometheus, Datadog, CloudWatch). Each exporter reacts to the same snapshot independently.

8. Game Engine Entity Systems

A game engine publishes collision, damage, and input events. Entities subscribe to the events they care about — the health system listens for damage events, the sound system listens for collision events, the UI listens for score events. No entity knows about the others; the event bus is the subject:

type EventBus struct {
    handlers map[EventType][]Handler
}

func (eb *EventBus) Publish(e Event) {
    for _, h := range eb.handlers[e.Type] {
        h.Handle(e)
    }
}

Decoupling entity systems this way makes it trivial to add or remove features (e.g. achievements) without touching existing systems.

9. File System Watchers

Tools like fsnotify implement Observer over the OS inode event stream. A watcher (subject) monitors a directory; subscribers (observers) react to create, modify, and delete events:

watcher.OnChange(func(path string, op Op) {
    if op == Write {
        reloadConfig(path)
    }
})

Hot-reloading config, triggering test runs on save, and invalidating build caches are all observers on the same file-change subject.

10. Ride-Sharing Driver Location Updates

A ride-sharing platform streams GPS location updates from a driver. Multiple observers react to each update: the passenger app displays the moving pin, the ETA service recalculates arrival time, the operations dashboard logs the trace, and the geofence service checks for zone entry/exit. Each observer is independent; the location stream is the shared subject. Adding surge-pricing zone detection is one new observer — nothing else changes.