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
- Differentiate between the core (or independent) functionality and the optional (or dependent) functionality.
- Model the independent functionality with a "subject" abstraction.
- Model the dependent functionality with an "observer" hierarchy.
- The Subject is coupled only to the Observer base class.
- The client configures the number and type of Observers.
- Observers register themselves with the Subject.
- The Subject broadcasts events to all registered Observers.
- 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
}