Observer is an Interface implemented by Multiple Classes
What is an interface, anyway?
This is one of those tricky areas where exact details vary a lot from language to language.
In Java, the Observer is almost always an interface implemented by multiple classes.
In C++, the Observer is likely to be an abstract class mixed in through multiple inheritance .
In Smalltalk, the weak typing allows the Observer interface to be merely an abstract idea rather than something directly implemented in code.
Observer design pattern
- Model the independent functionality with a subject abstraction
- Model the dependent functionality with observer hierarchy
- The Subject is coupled only to the Observer base class
- Observers register themselves with the Subject
- The Subject broadcasts events to all registered Observers
- Observers pull the information they need from the Subject
- Client configures the number and type of Observers
#include <iostream>
#include <vector>
using namespace std;
class Subject {
// 1. "independent" functionality
vector <class Observer * > views; // 3. Coupled only to "interface"
int value;
public:
void attach(Observer *obs) {
views.push_back(obs);
}
void setVal(int val) {
value = val;
notify();
}
int getVal() {
return value;
}
void notify();
};
class Observer {
// 2. "dependent" functionality
Subject *model;
int denom;
public:
Observer(Subject *mod, int div) {
model = mod;
denom = div;
// 4. Observers register themselves with the Subject
model->attach(this);
}
virtual void update() = 0;
protected:
Subject *getSubject() {
return model;
}
int getDivisor() {
return denom;
}
};
void Subject::notify() {
// 5. Publisher broadcasts
for (int i = 0; i < views.size(); i++)
views[i]->update();
}
class DivObserver: public Observer {
public:
DivObserver(Subject *mod, int div): Observer(mod, div){}
void update() {
// 6. "Pull" information of interest
int v = getSubject()->getVal(), d = getDivisor();
cout << v << " div " << d << " is " << v / d << '\n';
}
};
class ModObserver: public Observer {
public:
ModObserver(Subject *mod, int div): Observer(mod, div){}
void update() {
int v = getSubject()->getVal(), d = getDivisor();
cout << v << " mod " << d << " is " << v % d << '\n';
}
};
int main() {
Subject subj;
DivObserver divObs1(&subj, 4); // 7. Client configures the number and
DivObserver divObs2(&subj, 3); // type of Observers
ModObserver modObs3(&subj, 3);
subj.setVal(14);
}