Observer Design Pattern in C++: Before and after

Before

The number and type of “user interface” (or dependent) objects is hard-wired in the Subject class. The user has no ability to affect this configuration.

class DivObserver
{
    int m_div;
  public:
    DivObserver(int div)
    {
        m_div = div;
    }
    void update(int val)
    {
        cout << val << " div " << m_div << " is " << val / m_div << '\n';
    }
};

class ModObserver
{
    int m_mod;
  public:
    ModObserver(int mod)
    {
        m_mod = mod;
    }
    void update(int val)
    {
        cout << val << " mod " << m_mod << " is " << val % m_mod << '\n';
    }
};

class Subject
{
    int m_value;
    DivObserver m_div_obj;
    ModObserver m_mod_obj;
  public:
    Subject(): m_div_obj(4), m_mod_obj(3){}
    void set_value(int value)
    {
        m_value = value;
        notify();
    }
    void notify()
    {
        m_div_obj.update(m_value);
        m_mod_obj.update(m_value);
    }
};

int main()
{
  Subject subj;
  subj.set_value(14);
}

Output

14 div 4 is 3
14 mod 3 is 2


After

The Subject class is now decoupled from the number and type of Observer objects. The client has asked for two DivObserver delegates (each configured differently), and one ModObserver delegate.

class Observer
{
  public:
    virtual void update(int value) = 0;
};

class Subject
{
    int m_value;
    vector m_views;
  public:
    void attach(Observer *obs)
    {
        m_views.push_back(obs);
    }
    void set_val(int value)
    {
        m_value = value;
        notify();
    }
    void notify()
    {
        for (int i = 0; i < m_views.size(); ++i)
          m_views[i]->update(m_value);
    }
};

class DivObserver: public Observer
{
    int m_div;
  public:
    DivObserver(Subject *model, int div)
    {
        model->attach(this);
        m_div = div;
    }
     /* virtual */void update(int v)
    {
        cout << v << " div " << m_div << " is " << v / m_div << '\n';
    }
};

class ModObserver: public Observer
{
    int m_mod;
  public:
    ModObserver(Subject *model, int mod)
    {
        model->attach(this);
        m_mod = mod;
    }
     /* virtual */void update(int v)
    {
        cout << v << " mod " << m_mod << " is " << v % m_mod << '\n';
    }
};

int main()
{
  Subject subj;
  DivObserver divObs1(&subj, 4);
  DivObserver divObs2(&subj, 3);
  ModObserver modObs3(&subj, 3);
  subj.set_val(14);
}

Output

14 div 4 is 3
14 div 3 is 4
14 mod 3 is 2

Code examples