Design Patterns — A quick guide to Observer pattern.

  1. Register/Attach: Observers register themselves to the subject because they want to be notified when there is a change.
  2. Event: Events act as a trigger in the subject such that all the observers are notified.
  3. Notify: Depending on the implementation, the subject may “push” information to the observers, or, the observers may “pull” if they need information from the subject.
  4. Update: Observers update their state independently from other observers however their state might change depending on the triggered event.
  • The Observer is the parent class of the concrete observers. It contains a subject instance. When an observer is initialized, it registers/attaches itself to the subject.
  • The Subject class has a list or a collection of observers. When an event is triggered it calls the notify()operation which loops through all the observers by calling their update function.
  • All observers are attached/registered to the subject and they are notified when their football team scores (the trigger-event is if their team scores).
  • The observers update their behavior depending on the notification received.
#include <iostream>
#include <vector>
using namespace std;class Subject {
    vector < class Observer * > observers; 
    bool scored;                    // trigger, eventpublic:
    // register observers
    void attach(Observer *obs) {
        observers.push_back(obs);
    }
   
   // This is the EVENT
   // set the if scored and notify ALL observers
   void setScored(bool Score) {
      scored = Score;
      notify();
   }bool getScored() {
      return scored;
   }   // notify implementaion is further down
   // so that the script compiles and runs
   void notify();
};
class Observer 
{
    Subject *subj;
    int excitementLevel;               // state  public:
    Observer(Subject *mod, int excLevel) 
    {
        subj = mod;
        excitementLevel = excLevel;
        // Observers register/attach themselves with the Subject
        subj->attach(this);
    }    virtual void update() = 0;  protected:
    Subject *getSubject() {
       return subj;
    }    void setExcitementLevel(int excLevel) {
       excitementLevel = excLevel;
    }    int getExcitementLevel() {
       return excitementLevel;
    }
};
void Subject::notify() {
  for (int i = 0; i < observers.size(); i++)
    observers[i]->update();
}
class Old_ConcreteObserver: public Observer 
{
   public:
     // Calls parent constructor to register with subject
     Old_ConcreteObserver(Subject *mod, int div)
        :Observer(mod, div){}     // For older people, if the excitement level 
     // is over 150 they run risk of heart attack
     void update() 
     {
        bool scored = getSubject()->getScored(); 
        setExcitementLevel(getExcitementLevel() + 1);        if (scored && getExcitementLevel() > 150) 
        {
          cout << "Old Observer's team scored!!" 
               << " His excitement level is " 
               << getExcitementLevel() 
               << " watch out of heart attacks!" << endl;
        }else{
          cout << "Team didn't score. Yeeeih nothing to worry about"
               << endl;
        }
    } // end update()
};class Young_ConcreteObserver: public Observer 
{
   public:
     // Calls parent constructor to register with subject
     Young_ConcreteObserver(Subject *mod, int div)
       : Observer(mod, div){}     // For older people, if the excitement level 
     // is over 100 they run risk of heart attack
     void update() 
     {
        bool scored = getSubject()->getScored(); 
        setExcitementLevel(getExcitementLevel() + 1);        if (scored && getExcitementLevel() > 100) 
        {
          cout << "Young Observer's team scored!!" 
               << " His excitement level is " 
               << getExcitementLevel() 
               << " dont't drink and drive!!" << endl;
        }else{
          cout << "Team didn't score. Yeeh nothing to worry about"
               << endl;
       }
    } // end update()
};
int main() {
   Subject subj;
   Young_ConcreteObserver youngObs1(&subj, 100); 
   Old_ConcreteObserver oldObs1(&subj, 150); 
   Young_ConcreteObserver youngObs2(&subj, 52);
   subj.setScored(true);
}// Output
// Young Observer's team scored!! His excitement level is 101
// dont't drink and drive!! // Old Observer's team scored!! His excitement level is 151 watch 
// out of heart attacks! Team didn't score. // Yeeh nothing to worry about
  • There is no option for composition, as the Observer interface can be instantiated.
  • If the Observer is misused, it can easily add complexity and lead to performance issues.
  • Notifications can be unreliable and may result in race conditions or inconsistency.
  1. Design Patterns — A quick guide to Bridge Pattern.
  2. Design Patterns — A quick guide to Builder Pattern.
  3. Design Patterns — A quick guide to Decorator Pattern.
  4. Design Patterns — A quick guide to Facade Pattern.
  5. Design Patterns — A quick guide to Observer Pattern.
  6. Design Patterns — A quick guide to Singleton Pattern.

Data Driven Investor

from confusion to clarity, not insanity

Andreas Poyias

Written by

C++ software developer. PhD in the development of highly compressed data structures. I am a proud nerd that enjoys programming!

Data Driven Investor

from confusion to clarity, not insanity