Code:
#include <iostream>
#include <forward_list>
#include <unordered_map>
#include <memory> // shared_ptr
// event message types or view-controller input message types
// or observer message types
enum class EventMessageTypes {PLAYSOUND, HANDLEPHYSICS, LOG};
// Abstract class or interface class
class AbstractObserver
{
public:
virtual ~AbstractObserver() {}
virtual void OnNotify()=0;
virtual std::string GetName() const=0;
};
// event or view
class SoundEvent : public AbstractObserver
{
public:
explicit SoundEvent(const std::string& name) : mName(name)
{
}
void OnNotify() override
{
std::cout << mName << " sound event did something" << std::endl;
}
std::string GetName() const override
{
return mName;
}
private:
std::string mName;
};
class PhysicsEvent : public AbstractObserver
{
public:
explicit PhysicsEvent(const std::string& name) : mName(name)
{
}
void OnNotify() override
{
std::cout << mName << " physics event did something" << std::endl;
}
std::string GetName() const override
{
return mName;
}
private:
std::string mName;
};
class LogEvent : public AbstractObserver
{
public:
explicit LogEvent(const std::string& name) : mName(name)
{
}
void OnNotify() override
{
std::cout << mName << " log event did something" << std::endl;
}
std::string GetName() const override
{
return mName;
}
private:
std::string mName;
};
class AbstractObservable
{
public:
AbstractObservable() {};
virtual ~AbstractObservable() {}
virtual void AddObserver(EventMessageTypes eventMessage,
std::shared_ptr<AbstractObserver>& observer)
{
auto it = mObservers.find(eventMessage);
if( it==mObservers.end() )
{
mObservers[eventMessage] = ObserversList();
}
mObservers[eventMessage].push_front(observer);
}
virtual void RemoveObserver(EventMessageTypes eventMessage,
std::shared_ptr<AbstractObserver>& observer)
{
auto it = mObservers.find(eventMessage);
if(it != mObservers.end())
{
ObserversList& observersList = mObservers[eventMessage];
for(ObserversList::iterator li = observersList.begin();
li != observersList.end(); )
{
if( (*li) == observer )
{
std::cout << "Goodbye " << observer->GetName() << std::endl;
observersList.remove(observer);
break;
}
else
{
++li;
}
}
}
}
virtual void NotifyAll()
{
for(ObserversMap::iterator it = mObservers.begin();
it!=mObservers.end(); ++it)
{
for(auto& o : mObservers[it->first])
{
o->OnNotify();
}
}
}
virtual void Notify(EventMessageTypes message)
{
for(auto& o: mObservers[message])
{
o->OnNotify();
}
}
private:
// Two typedefs here
// first for the forward_list of observers
// second for the unordered_map of EventMessageTypes map key
// and ObserversList map value
typedef std::forward_list<std::shared_ptr<AbstractObserver>> ObserversList;
typedef std::unordered_map<EventMessageTypes, ObserversList> ObserversMap;
ObserversMap mObservers;
};
class ModelChildObservable : public AbstractObservable
{
public:
EventMessageTypes eventMessage;
};
int main()
{
ModelChildObservable modelChildObservable;
std::shared_ptr<AbstractObserver> observable1a = std::make_shared<SoundEvent>("observable1a");
std::shared_ptr<AbstractObserver> observable1b = std::make_shared<SoundEvent>("observable1b");
std::shared_ptr<AbstractObserver> observable2 = std::make_shared<PhysicsEvent>("observable2");
std::shared_ptr<AbstractObserver> observable3 = std::make_shared<LogEvent>("observable3");
modelChildObservable.AddObserver(EventMessageTypes::PLAYSOUND, observable1a);
modelChildObservable.AddObserver(EventMessageTypes::PLAYSOUND, observable1b);
modelChildObservable.AddObserver(EventMessageTypes::HANDLEPHYSICS, observable2);
modelChildObservable.AddObserver(EventMessageTypes::LOG, observable3);
modelChildObservable.NotifyAll();
std::cout << std::endl;
modelChildObservable.Notify(EventMessageTypes::PLAYSOUND);
std::cout << std::endl;
modelChildObservable.RemoveObserver(EventMessageTypes::PLAYSOUND, observable1a);
std::cout << std::endl;
modelChildObservable.Notify(EventMessageTypes::PLAYSOUND);
std::cout << std::endl;
return 0;
}
No comments:
Post a Comment