//
Purpose.  Observer                   class Obs;
//
//
Discussion.  On the left: Subject    class Subject {
// has hard-wired the
number and type   public:
// of
"dependent" objects, the compil-    
Subject();
// er must have the declaration of the     void attach( Obs* );
// concrete Obs
classes to compile         void setVal(
int );
// Subject's decl, the Obs classes ex-     int  getVal();
//
ercise no reuse of i/f or impl, and    
void notify();
// Subject "pushes" updates to the
Obs  private:
// objects.  On the right: Subject is      Obs* 
obs_[10];
// decoupled from the number, type,        int  
num_, val_;
// and declaration of concrete Obs      };
// subclasses; the Obs objects
accept
// polymorphism; and Subject broad-     class Obs { public:
// casts that a change has
occurred        virtual void update() =
0;
// followed by Obs objects requesting  
protected:
// just the info that they want.           Subject*  sub_;
                                           int       div_;
class DivObs { public:                  };
   DivObs( int );                       class DivObs : public Obs { public:
   void update( int );                     DivObs( Subject*, int
);
private:                                   void update();
   int 
div_;                          
};
};                                      class ModObs : public Obs {
public:
class ModObs { public:                     ModObs( Subject*, int );
   ModObs( int );                          void update();
   void update( int );                  };
private:
   int 
div_;                          
Subject::Subject()     { num_ =
0; }
};                                      int  Subject::getVal() { return val_; }
                                        void
Subject::attach( Obs* o ) {
class Subject {                            obs_[num_++] = o; }
public:                                 void
Subject::setVal( int v ) {
  
Subject();                             
val_ = v;   notify(); }
   void setVal( int );                  void Subject::notify()
{
private:                                   for (int i=0; i < num_;
i++)
   int     val_;                              obs_[i]->update(); }
   DivObs 
div_;
   ModObs  mod_;                        DivObs::DivObs( Subject* s, int d ) {
};                                         sub_
= s;  div_ = d;
                                          
sub_->attach( this ); }
Subject::Subject() : div_(4),
mod_(3)   void DivObs::update() {
   { }                                     int v =
sub_->getVal();
void Subject::setVal( int v ) {            cout << v << "
div " << div_
   val_ =
v;                                 
<< " is " << v / div_ << endl; }
   div_.update( val_ );                 ModObs::ModObs( Subject* s,
int d ) {
   mod_.update( val_ );
}                  sub_ = s;  div_ = d;
                                           sub_->attach( this );
}
DivObs::DivObs( int d ) { div_ = d; }  
void ModObs::update() {
void DivObs::update( int v ) {             int v = sub_->getVal();
   cout << v << " div "
<< div_            cout << v << " mod "
<< div_
      << "
is " << v / div_ << endl; }        << " is " << v % div_ << endl;
}
ModObs::ModObs( int d ) { div_ = d; }
void ModObs::update( int v )
{          void main( void )
   cout << v << " mod "
<< div_         {
      << " is " << v %
div_ << endl; }     Subject  subj;
                                           DivObs   divObs1( &subj, 4 );
void main(
void )                         
DivObs   divObs2( &subj, 3
);
{                                          ModObs   modObs3( &subj, 3 );
   Subject 
subj;                         
subj.setVal( 14 );
  
subj.setVal( 14 );                  
}
}
                                        // 14 div 4 is 3
// 14
div 4 is 3                        // 14
div 3 is 4
// 14 mod 3 is 2                        // 14 mod 3 is 2
//
Purpose.  Observer design pattern
//
1. Model the "independent" functionality with a "subject"
abstraction
// 2. Model the "dependent" functionality with
"observer" hierarchy
// 3. The Subject is coupled only to the
Observer base class
// 4. Observers register themselves with the
Subject
// 5. The Subject broadcasts events to all registered
Observers
// 6. Observers "pull" the information they need from
the Subject
// 7. 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';
}  };
void main( void ) {
   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 );
}
//
14 div 4 is 3
// 14 div 3 is 4
// 14 mod 3 is 2
//
Purpose.  Observer design pattern, class
inheritance vs type inheritance
// SensorSystem is the
"subject".  Lighting, Gates,
and Surveillance are the
// "views".  The subject is only coupled to the "abstraction" of
AlarmListener.
// An object's class defines how the object is
implemented.  In contrast, an
//
object's type only refers to its interface. 
Class inheritance defines an
// object's implementation in terms of
another object's implementation. 
Type
// inheritance describes when an object can be used in place
of another.
// [GoF, pp13-17]
#include <iostream>
#include
<vector>
using namespace std;
class AlarmListener {
public: virtual void alarm() = 0; };
class SensorSystem {
   vector<AlarmListener*>
listeners;
public:
   void
attach( AlarmListener* al ) { listeners.push_back( al ); }
   void soundTheAlarm() {
      for (int i=0; i < listeners.size();
i++)
        
listeners[i]->alarm();
} 
};
class Lighting : public AlarmListener {
   public: /*virtual*/ void alarm() { cout
<< "lights up" << '\n'; }
};
class Gates
: public AlarmListener {
   public:
/*virtual*/ void alarm() { cout << "gates close" << '\n';
}
};
class CheckList {
  
virtual void localize() { cout << "   establish a perimeter" << '\n'; }
   virtual void isolate()  { cout << "   isolate the grid"      << '\n'; }
   virtual void identify() { cout <<
"   identify the source"   << '\n'; }
public:
   void byTheNumbers() {  // Template Method design pattern
      localize();
      isolate();
      identify();
}  };
                     // class inheri.  // type inheritance
class Surveillance : public CheckList,
public AlarmListener {
  
/*virtual*/ void isolate() { cout << "   train the cameras" << '\n';
}
public:
   /*virtual*/ void
alarm() {
      cout <<
"Surveillance - by the numbers:" << '\n';
      byTheNumbers();
}  };
void main( void ) {
   SensorSystem ss;
   ss.attach( &Gates()        );
   ss.attach( &Lighting()    
);
   ss.attach(
&Surveillance() );
  
ss.soundTheAlarm();
}
// gates close
// lights
up
// Surveillance - by the numbers:
//    establish a perimeter
//    train the cameras
//   
identify the source
// Purpose.  Observer and Mediator demo
// 
//
Observer - 1. Sender is coupled to a Receiver interface
//            2. Receivers register with
Sender
//            3. Sender
broadcasts (in the blind) to all Receivers
// 
// Mediator - 4.
Sender(s) has handle to Mediator
//            5. Mediator has handle to Receiver(s)
//            6. Sender(s) sends to
Mediator
//            7. Mediator
sends to Receiver(s)
#include <iostream>
#include
<vector>
using namespace std;
void gotoxy( int, int );
class
Observer { public: virtual void update( int ) = 0; };
class Mediator
{
   vector<Observer*>
groups[3];         // 1. Sender is
coupled to an interface
public:
  
enum Message { ODD, EVEN, THREE };  
// 1. Sender is coupled to an interface
   void attach( Observer* o, Message type ) {
groups[type].push_back( o ); }
  
void disseminate( int num ) {
         if (num % 2 == 1) 
// odd      // 3,7.
Sender/Mediator broadcasts
           
for (int i=0; i < groups[0].size(); i++)
groups[0][i]->update(num);
        
else               // even
            for (int i=0; i <
groups[1].size(); i++) groups[1][i]->update(num);
         if (num % 3 == 0)  // /3
            for (int i=0; i < groups[2].size(); i++)
groups[2][i]->update(num);
} 
};
class OddObserver : public Observer {
   int col, row;
public:
   OddObserver( Mediator& med, int c )
{
      col = c;           row = 3;
      gotoxy( col, 1 );  cout << "Odd";
      gotoxy( col, 2 );  cout << "---";
      med.attach( this, Mediator::ODD );  // 2,5. Receivers register with Sender
   }
  
void update( int num ) { gotoxy( col, row++ );  cout << num; }
};
class EvenObserver :
public Observer {
   int col,
row;
public:
   EvenObserver(
Mediator& med, int c ) {
     
col = c;           row = 3;
      gotoxy( col, 1 );  cout << "/2";
      gotoxy( col, 2 );  cout << "--";
      med.attach( this, Mediator::EVEN
);
   }
   void update( int num ) { gotoxy( col, row++
);  cout << num; }
};
class
ThreeObserver : public Observer {
  
int col, row;
public:
  
ThreeObserver( Mediator& med, int c ) {
      col = c;           row = 3;
     
gotoxy( col, 1 );  cout <<
"/3";
      gotoxy( col,
2 );  cout <<
"--";
      med.attach(
this, Mediator::THREE );
   }
   void update( int num ) { gotoxy( col, row++
);  cout << num; }
};
class
Publisher { public:            // 6.
Sender sends to Mediator
  
Publisher( Mediator& med ) { for (int i=1; i < 10; i++)
med.disseminate(i); }
};
void main( void ) {
   Mediator  
mediator;
  
OddObserver(   mediator,  1 );
  
EvenObserver(  mediator, 11
);
   ThreeObserver( mediator, 21
);
   Publisher  producer( mediator );  // 4. Sender has handle to Mediator
}
//
Odd       /2        /3
// ---      
--        --
// 1         2         3
// 3        
4         6
// 5         6         9
// 7        
8
// 9
// Purpose.  TypedMessage - embellished Observer,
decoupled messaging
//
// Messages inherit from
TypedMessage<self>
// Message listeners inherit from many
Message::Handlers
// Application tells message to
publish/broadcast/notify
// Messages are the subject (receive
registrations from subscribers)
// Subsystems are the observers (receive
broadcast messages)
// TypedMessage accomodates everything: registration,
containment, and
//   notification
of observers
#include <iostream>
#include
<vector>
#include <string>
using namespace std;
template
<class T>
class TypedMessage {
   static vector<Handler*> registry;
public:
   class Handler {
   public:
      Handler() { TypedMessage<T>::registerHandler( this );
}
      virtual void handleEvent(
const T* t ) = 0;
   };
   void notify() {
      for (int i=0; i < registry.size();
i++)
        
registry.at(i)->handleEvent( (T*)this );
   }
  
static void registerHandler( Handler* h ) { registry.push_back( h );
}
};
class On : public TypedMessage<On>  {
  
string comment;
public:
  
On( string str )   { comment =
str; }
   void start() const { cout
<< "OnEvent.start - " << comment << '\n'; }
};
vector<TypedMessage<On>::Handler*>
TypedMessage<On>::registry;
class Off : public
TypedMessage<Off>  {
   string comment;
public:
   Off( string str ) { comment = str; }
   void stop() const { cout <<
"OffEvent.stop - " << comment << '\n'; }
};
vector<TypedMessage<Off>::Handler*>
TypedMessage<Off>::registry;
class MasterConsole : public
On::Handler, public Off::Handler { public:
   void handleEvent( const On* msg ) {
      cout << "MasterConsole -
";  msg->start(); }
   void handleEvent( const Off* msg ) {
      cout << "MasterConsole -
";  msg->stop(); }
};
class
PowerMonitor : public On::Handler { public:
   void handleEvent( const On* msg ) {
      cout << "PowerMonitor -
";  msg->start(); }
};
void
main( void ) {
  
MasterConsole  mc;
   PowerMonitor   pm;
   On oneEvent(
"lights" );  Off thrEvent(
"elevators" );
   On
twoEvent( "hvac" );    Off
fouEvent( "frontDoor" ); 
  
oneEvent.notify(); 
twoEvent.notify();
  
thrEvent.notify(); 
fouEvent.notify();
}
// MasterConsole - OnEvent.start -
lights
// PowerMonitor - OnEvent.start - lights
// MasterConsole -
OnEvent.start - hvac
// PowerMonitor - OnEvent.start - hvac
//
MasterConsole - OffEvent.stop - elevators
// MasterConsole - OffEvent.stop
- frontDoor