Listing 5
// test application for messaging system
#include "Messaging.h"
#include <iostream>
#include <string>
using namespace std;
// some listener interface
struct MartianAlertListener
{
virtual void martianLanded(const string &where) = 0;
};
// some other listener interface
struct NuclearPSListener
{
virtual void itIsHot(int temp) = 0;
virtual void itIsTooLate() = 0;
};
// a commong functionality of the normal person and
// the technician in the nuclear power station
class Person
{
public:
Person(const string &name) : name_(name) {}
string getName() const { return name_; }
private:
string name_;
};
// a class representing the normal person
// normal person is interested in the MartianAlert events
class NormalPerson : public Person,
public MartianAlertListener
{
public:
NormalPerson(const string &name)
: Person(name) {}
// here, the Person receives the notification
virtual void martianLanded(const string &where)
{
cout << getName() << ": martian landed "
<< where << endl;
}
};
// a context structure for MartianAlert events,
// holding the info considering the landing place
struct MartianContext
{
string where_;
};
// the helper typedef
typedef
Messaging<MartianAlertListener, MartianContext>
MartianAlertSource;
// another class, representing a technician in
// the nuclear power station
// the technician is interested in
// the events related to his job
class Technician : public Person,
public NuclearPSListener
{
public:
Technician(const string &name)
: Person(name) {}
void itIsHot(int temp)
{
cout << getName() << ": there is " << temp
<< " degrees in the reactor" << endl;
}
void itIsTooLate()
{
cout << getName() << ": BANG!" << endl;
}
};
// a context structure for events in the power station,
// holding info considering:
// 1. what has happened
// 2. what is the temperature in the reactor
struct NuclearPSContext
{
enum eWhat {it_is_hot, it_is_too_late} whathappened_;
int temp_;
};
// the helper typedef
typedef
Messaging<NuclearPSListener, NuclearPSContext>
NuclearPSSource;
// the ultimate source of events
// note multiple inheritance
// (one for each listener type)
class EventSource : public MartianAlertSource,
public NuclearPSSource
{
public:
// inherited from MartianAlertSource
void dispatchEvent(MartianAlertListener *p,
const MartianContext &context)
{
// just call the listener
p->martianLanded(context.where_);
}
// inherited from NuclearPSSource
void dispatchEvent(NuclearPSListener *p,
const NuclearPSContext &context)
{
// we have a choice and parameters with some details
if (context.whathappened_ ==
NuclearPSContext::it_is_hot)
p->itIsHot(context.temp_);
else
p->itIsTooLate();
}
// play a little with events
void go()
{
// send a martian alert
MartianContext ctx1;
ctx1.where_ = "in the garden";
// note: if this class inherits from
// only one event source base,
// the operator:: is not needed
MartianAlertSource::raiseEvent(ctx1);
// send a temperature report
NuclearPSContext ctx2;
ctx2.whathappened_ = NuclearPSContext::it_is_hot;
ctx2.temp_ = 5000;
NuclearPSSource::raiseEvent(ctx2);
// send a "too late" event notification
NuclearPSContext ctx3;
ctx3.whathappened_ = NuclearPSContext::it_is_too_late;
NuclearPSSource::raiseEvent(ctx3);
}
};
int main()
{
// these are object which will receive
// event notifications:
NormalPerson john("John");
NormalPerson jenny("Jenny");
NormalPerson mike("Mike");
Technician tech1("technician 1");
Technician tech2("technician 2");
// this is a source of events
EventSource source;
// register objects as listeners in an event source
// note: if an event source inherits from only one
// event source base, the :: selectors are not needed
source.MartianAlertSource::addListener(&john);
source.MartianAlertSource::addListener(&jenny);
source.MartianAlertSource::addListener(&mike);
source.NuclearPSSource::addListener(&tech1);
source.NuclearPSSource::addListener(&tech2);
// play
source.go();
return 0;
}