#pragma once #include #include template class Observable; /** * An observer which can be mixed in as a baseclass. Implement onNotify as a method in your class. */ template class Observer { Observable *observed; public: Observer() : observed(NULL) {} virtual ~Observer(); void observe(Observable *o); private: friend class Observable; protected: virtual void onNotify(T arg) = 0; }; /** * An observer that calls an arbitrary method */ template class CallbackObserver : public Observer { typedef void (Callback::*ObserverCallback)(T arg); Callback *objPtr; ObserverCallback method; public: CallbackObserver(Callback *_objPtr, ObserverCallback _method) : objPtr(_objPtr), method(_method) {} protected: virtual void onNotify(T arg) { (objPtr->*method)(arg); } }; /** * An observable class that will notify observers anytime notifyObservers is called. Argument type T can be any type, but for * performance reasons a pointer or word sized object is recommended. */ template class Observable { std::list *> observers; public: /** * Tell all observers about a change, observers can process arg as they wish */ void notifyObservers(T arg) { for (typename std::list *>::const_iterator iterator = observers.begin(); iterator != observers.end(); ++iterator) { (*iterator)->onNotify(arg); } } private: friend class Observer; // Not called directly, instead call observer.observe void addObserver(Observer *o) { observers.push_back(o); } void removeObserver(Observer *o) { observers.remove(o); } }; template Observer::~Observer() { if (observed) observed->removeObserver(this); observed = NULL; } template void Observer::observe(Observable *o) { o->addObserver(this); }