Observer sample code

#include <stdio.h>

// Singly-linked list from Ken Russell.  Based on libg++ but as a template.
#include "SLList.h"

class Subject;

class Observer {
public:
  virtual ~Observer() {}
  virtual void Update(Subject *s) = 0;
};

class Subject {
public:
  virtual ~Subject() {}

  void Attach(Observer *o);
  void Detach(Observer *o);
  void Notify();
private:
  SLList<Observer*> observers;
};

void Subject::Attach(Observer *o) {
  observers.append(o);
}

void Subject::Detach(Observer *o) {
  observers.del(o);
}

void Subject::Notify() {
  for(Pix p = observers.first(); p; observers.next(p)) {
    observers(p)->Update(this);
  }
}

/*****************************************************************************/

class MySubject : public Subject {
public:
  MySubject() { x = 0; }
  int GetX() { return x; }
  void SetX(int new_x) { x = new_x; Notify(); }
private:
  int x;
};

// Observer for MySubject
class MyObserver : public Observer {
public:
  virtual ~MyObserver() { subject->Detach(this); }
  virtual void Watch(MySubject &s) { 
    s.Attach(this); subject = &s; Update(&s); 
  }
  virtual void Update(Subject *s) {}
protected:
  MySubject *subject;
};

/*****************************************************************************/

// Two specific Observers: 
// one that echoes subject->x in decimal
// and one that echoes in hex.

class DecimalObserver : public MyObserver {
public:
  virtual void Update(Subject *s);
};

void DecimalObserver::Update(Subject *s)
{
  // This equality allows us to use a MySubject object instead
  // of a Subject object.
  if(subject == s) {
    printf("decimal: %d\n", subject->GetX());
  }
}

class HexObserver : public MyObserver {
public:
  virtual void Update(Subject *s);
};

void HexObserver::Update(Subject *s)
{
  // This equality allows us to use a MySubject object instead
  // of a Subject object.
  if(subject == s) {
    printf("hex: %x\n", subject->GetX());
  }
}

/*****************************************************************************/

main()
{
  MySubject subject;
  DecimalObserver decimal;
  decimal.Watch(subject);
  HexObserver hex;
  hex.Watch(subject);

  int i;
  // X is echoed in decimal and hex each time
  for(i = 0; i < 100; i += 10) {
    subject.SetX(i);
  }
  subject.Detach(&decimal);

  // Now only in hex
  for(; i < 200; i += 10) {
    subject.SetX(i);
  }
}

Thomas Minka
Last modified: Tue Jan 7 14:10:53 EST 1997