← All Patterns
behavioral4 participants

Observer

Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

The Problem

You have an object whose state other objects depend on. Polling is wasteful — every dependent checks the object repeatedly. Direct coupling is brittle — the subject has to know every dependent by type and call them manually.

Structure

Subjectnotify()subscribe(cb)notify(v)Loggerupdate(v)Displayupdate(v)Alerterupdate(v)subscribe(cb)1:N dependency

Execution Walkthrough

1

Subscribe

Observers register themselves with the Subject by calling subscribe(). The Subject stores callbacks in a list.

2

State changes

3

notify() fires

4

Each update()

5

Decoupled

Code Comparison

The naive approach — Subject directly calls each dependent. Adding a new consumer requires modifying Subject.

// BAD: Subject tightly coupled to every consumer
class Signal {
  int value_ = 0;
  Logger   logger_;
  Display  display_;
  Alerter  alerter_;

public:
  void set_value(int v) {
    value_ = v;
    logger_.log(v);      // direct call — brittle
    display_.render(v);  // must modify Signal to add/remove
    alerter_.check(v);   // any consumer changes break this class
  }
};

Full C++ Implementation

C++ · Observer
#include <functional>
#include <vector>
#include <string>
#include <iostream>

class Subject {
  std::vector<std::function<void(int)>> observers_;
  int value_ = 0;
public:
  void subscribe(std::function<void(int)> cb) {
    observers_.push_back(std::move(cb));
  }
  void set_value(int v) {
    value_ = v;
    for (auto& cb : observers_) cb(v);
  }
  int get() const { return value_; }
};

// Concrete observers — just lambdas or structs
struct Logger {
  void on_change(int v) {
    std::cout << "[log] value=" << v << "\n";
  }
};

struct Alerter {
  int threshold;
  void on_change(int v) {
    if (v > threshold)
      std::cout << "[alert] exceeded " << threshold << "\n";
  }
};

int main() {
  Subject signal;
  Logger  logger;
  Alerter alerter{100};

  signal.subscribe([&](int v){ logger.on_change(v); });
  signal.subscribe([&](int v){ alerter.on_change(v); });
  signal.subscribe([](int v){
    std::cout << "[display] " << v << "\n";
  });

  signal.set_value(42);   // Logger, Display fire
  signal.set_value(150);  // Logger, Display, Alert fire
}

Participants

SubjectObserverConcreteSubjectConcreteObserver

Where it is used

EDA simulators

Xcelium's event-driven propagation — a signal change notifies all sensitive processes registered to that net.

Qt framework

Signals and slots: QPushButton::clicked() notifies any slot connected to it — GUI decoupled from logic.

Node.js

EventEmitter.on('data', cb) — fs.ReadStream notifies all listeners on each chunk read from disk.

Financial systems

A market data feed notifies strategy engines, risk monitors, and loggers simultaneously on each tick.

Strategy