Observer


Description:

A way of notifying change to a number of classes

The Observer defines a one-to-many relationship so that when one object changes state, the others are notified and updated automatically.

Intent

  • Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
  • Encapsulate the core (or common or engine) components in a Subject abstraction, and the variable (or optional or user interface) components in an Observer hierarchy.
  • The "View" part of Model-View-Controller.

    Example:

    Note
    

Idea:

Check list

  1. Differentiate between the core (or independent) functionality and the optional (or dependent) functionality.
  2. Model the independent functionality with a "subject" abstraction.
  3. Model the dependent functionality with an "observer" hierarchy.
  4. The Subject is coupled only to the Observer base class.
  5. The client configures the number and type of Observers.
  6. Observers register themselves with the Subject.
  7. The Subject broadcasts events to all registered Observers.
  8. The Subject may "push" information at the Observers, or, the Observers may "pull" the information they need from the Subject.

Code:

#include <iostream>
#include <memory>
#include <vector>
#include <cmath>

using namespace std;

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

class Subject{
private:
    int m_value;
    vector<Observer *> 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{
private:
    int m_div;
public:
    DivObserver(Subject *model, int div){
        model->attach(this);
        m_div = div;
    }
    void update(int v) override{
        cout << v << " div " << m_div << " is " << v / m_div << '\n';
    }
};

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

int main(){
    Subject subj;
    DivObserver div_obs1(&subj, 4);
    DivObserver div_obs2(&subj, 3);
    ModObserver mod_obs3(&subj, 3);

    subj.set_val(14); // observer update is HERE!
    // 14 div 4 is 3
    // 14 div 3 is 4
    // 14 mod 3 is 2
}

results matching ""

    No results matching ""