Re: Observer Design Pattern
Krivenok Dmitry wrote:
Hello All!
I am trying to implement my own Design Patterns Library.
You can't do that in general. Design Patterns are at a level higher
than simple code reuse. That said...
The classic "pull model" can be implemented like this:
class Observer
{
public:
virtual ~Observer() { }
virtual void update() = 0;
};
class Subject
{
std::set< Observer* > observers;
public:
void attach( Observer* o ) {
observers.insert( o );
}
void detach( Observer* o ) {
observers.erase( o );
}
void notify() {
for_each( observers.begin(), observers.end(),
mem_fun( &Observer::update ) );
}
};
class MySubject : public Subject
{
int state;
public:
int getState() const { return state; }
void setState( int value ) { state = value; notify(); }
};
class MyObserver : public Observer
{
MyObserver( const MyObserver& );
MyObserver& operator=( const MyObserver& );
MySubject* subject;
public:
MyObserver( MySubject* subject_ ): subject( subject_ ) {
subject->attach( this );
}
~MyObserver() {
subject->detach( this );
}
void update() {
// do something with subject->getState();
}
};
However, I have found the "push model" to be much more useful:
template < typename Observer >
class Subject {
std::set< Observer* > observers;
public:
void attach( Observer* o ) {
observers.insert( o );
}
void detach( Observer* o ) {
observers.erase( o );
}
template < typename ConcreteSubject >
void notify( const ConcreteSubject* cs, void (Observer::*fn)( const
ConcreteSubject* ) ) {
std::set< Observer* >::iterator it = observers.begin();
while ( it != observers.end() ) {
Observer* ob( *it++ );
(ob->*fn)( cs );
}
}
};
I don't understand why GoF includes GetState method in Subject's
interface.
They did that because they were looking at SmallTalk examples which
didn't translate well to C++
Main question:
How to avoid type switching in ConcreteObserver::Update(Subject* s)?
As I showed above.