home
#include <iostream>
#include <iterator>
#include <deque>
// Implementation of the observer pattern
// its implemented in the java way :D
template <typename T>
class Observer
{
public:
Observer(){}
virtual ~Observer () {}
virtual void update (T * arg){}
};
template <typename T>
class Observable
{
private:
T * self;
typedef std::deque<Observer<T> *> ObserverContainer;
ObserverContainer observers;
public:
Observable (T * self_){self=self_;}
virtual ~Observable(){}
void addObserver(Observer<T> * ob)
{observers.push_back(ob);}
void deleteObserver (Observer<T> * ob)
{
// Before you use this method you shoule be
// sure you are not doing nasty things..., since
// it can carry HUGE memory problems, in this
// case we are deleting observers using its
// pointer for looking for it. Think about the
// problems this can carry on!!!! (stored Objects,
// objects stored on different thread stacks...)
// To solve this, assign an OID to each observer,
// using a Creator class, and store in a map in the observable!!.
observers.erase(std::remove_if(observers.begin()
,observers.end()
,std::bind2nd(std::equal_to<Observer <T> *>(),ob)));
}
void cleanObservers()
{
observers.clean();
}
void notifyObservers()
{
// Since this declaration is template argument dependant
// its necessary to add the typename keyword.
typename ObserverContainer::iterator it;
for (it = observers.begin()
;it!=observers.end()
;(*it++)->update(self));
}
};
class View : public Observable<View>
{
private:
std::string name;
public:
View(std::string name_):Observable<View>(this), name(name_){}
~View(){}
std::string getName() {return this->name;}
};
class ViewController : public Observer<View>
{
public:
ViewController(){}
~ViewController(){}
void update (View * arg)
{
std::cout<<arg->getName()<<" Has changed!!"<<std::endl;
}
};
int main (int argc, char * argv)
{
ViewController vc;
View v1 ("View 1");
View v2 ("View 2");
v1.addObserver(&vc);
v2.addObserver(&vc);
v1.notifyObservers();
v2.notifyObservers();
return 0;
}