/* * C++ Design Patterns: Observer * Author: Jakub Vojvoda [github.com/JakubVojvoda] * 2016 * * Source code is licensed under MIT License * (for more details see LICENSE) * */ #include #include class Subject; /* * Observer * defines an updating interface for objects that should be notified * of changes in a subject */ class Observer { public: virtual ~Observer() {} virtual int getState() = 0; virtual void update( Subject *subject ) = 0; // ... }; /* * Concrete Observer * stores state of interest to ConcreteObserver objects and * sends a notification to its observers when its state changes */ class ConcreteObserver : public Observer { public: ConcreteObserver( const int state ) : observer_state( state ) {} ~ConcreteObserver() {} int getState() { return observer_state; } void update( Subject *subject ); // ... private: int observer_state; // ... }; /* * Subject * knows its observers and provides an interface for attaching * and detaching observers */ class Subject { public: virtual ~Subject() {} void attach( Observer *observer ) { observers.push_back(observer); } void detach( const int index ) { observers.erase( observers.begin() + index ); } void notify() { for ( unsigned int i = 0; i < observers.size(); i++ ) { observers.at( i )->update( this ); } } virtual int getState() = 0; virtual void setState( const int s ) = 0; // ... private: std::vector observers; // ... }; /* * Concrete Subject * stores state that should stay consistent with the subject's */ class ConcreteSubject : public Subject { public: ~ConcreteSubject() {} int getState() { return subject_state; } void setState( const int s ) { subject_state = s; } // ... private: int subject_state; // ... }; void ConcreteObserver::update( Subject *subject ) { observer_state = subject->getState(); std::cout << "Observer state updated." << std::endl; } int main() { ConcreteObserver observer1( 1 ); ConcreteObserver observer2( 2 ); std::cout << "Observer 1 state: " << observer1.getState() << std::endl; std::cout << "Observer 2 state: " << observer2.getState() << std::endl; Subject *subject = new ConcreteSubject(); subject->attach( &observer1 ); subject->attach( &observer2 ); subject->setState( 10 ); subject->notify(); std::cout << "Observer 1 state: " << observer1.getState() << std::endl; std::cout << "Observer 2 state: " << observer2.getState() << std::endl; delete subject; return 0; }