|
| 1 | +/* |
| 2 | + * C++ Design Patterns: Observer |
| 3 | + * Author: Jakub Vojvoda [github.com/JakubVojvoda] |
| 4 | + * 2016 |
| 5 | + * |
| 6 | + * Source code is licensed under MIT License |
| 7 | + * (for more details see LICENSE) |
| 8 | + * |
| 9 | + */ |
| 10 | + |
| 11 | +#include <iostream> |
| 12 | +#include <vector> |
| 13 | + |
| 14 | +class Subject; |
| 15 | + |
| 16 | +/* |
| 17 | + * Observer |
| 18 | + * defines an updating interface for objects that should be notified |
| 19 | + * of changes in a subject |
| 20 | + */ |
| 21 | +class Observer { |
| 22 | +public: |
| 23 | + virtual int getState() = 0; |
| 24 | + virtual void update(Subject *subject) = 0; |
| 25 | + // ... |
| 26 | +}; |
| 27 | + |
| 28 | +/* |
| 29 | + * Concrete Observer |
| 30 | + * stores state of interest to ConcreteObserver objects and |
| 31 | + * sends a notification to its observers when its state changes |
| 32 | + */ |
| 33 | +class ConcreteObserver : public Observer { |
| 34 | +public: |
| 35 | + ConcreteObserver(int state) |
| 36 | + : observer_state(state) {} |
| 37 | + |
| 38 | + int getState() { |
| 39 | + return observer_state; |
| 40 | + } |
| 41 | + |
| 42 | + void update(Subject *subject); |
| 43 | + // ... |
| 44 | + |
| 45 | +private: |
| 46 | + int observer_state; |
| 47 | + // ... |
| 48 | +}; |
| 49 | + |
| 50 | +/* |
| 51 | + * Subject |
| 52 | + * knows its observers and provides an interface for attaching |
| 53 | + * and detaching observers |
| 54 | + */ |
| 55 | +class Subject { |
| 56 | +public: |
| 57 | + void attach(Observer *observer) { |
| 58 | + observers.push_back(observer); |
| 59 | + } |
| 60 | + |
| 61 | + void detach(int index) { |
| 62 | + observers.erase(observers.begin() + index); |
| 63 | + } |
| 64 | + |
| 65 | + void notify() { |
| 66 | + for (unsigned int i = 0; i < observers.size(); i++) { |
| 67 | + observers.at(i)->update(this); |
| 68 | + } |
| 69 | + } |
| 70 | + |
| 71 | + virtual int getState() = 0; |
| 72 | + virtual void setState(int s) = 0; |
| 73 | + // ... |
| 74 | + |
| 75 | +private: |
| 76 | + std::vector<Observer *> observers; |
| 77 | + // ... |
| 78 | +}; |
| 79 | + |
| 80 | +/* |
| 81 | + * Concrete Subject |
| 82 | + * stores state that should stay consistent with the subject's |
| 83 | + */ |
| 84 | +class ConcreteSubject : public Subject { |
| 85 | +public: |
| 86 | + int getState() { |
| 87 | + return subject_state; |
| 88 | + } |
| 89 | + |
| 90 | + void setState(int s) { |
| 91 | + subject_state = s; |
| 92 | + } |
| 93 | + // ... |
| 94 | + |
| 95 | +private: |
| 96 | + int subject_state; |
| 97 | + // ... |
| 98 | +}; |
| 99 | + |
| 100 | +void ConcreteObserver::update(Subject *subject) { |
| 101 | + observer_state = subject->getState(); |
| 102 | + std::cout << "Observer state updated." << std::endl; |
| 103 | +} |
| 104 | + |
| 105 | + |
| 106 | +int main() |
| 107 | +{ |
| 108 | + ConcreteObserver observer1(1); |
| 109 | + ConcreteObserver observer2(2); |
| 110 | + |
| 111 | + std::cout << "Observer 1 state: " << observer1.getState() << std::endl; |
| 112 | + std::cout << "Observer 2 state: " << observer2.getState() << std::endl; |
| 113 | + |
| 114 | + Subject *subject = new ConcreteSubject; |
| 115 | + subject->attach(&observer1); |
| 116 | + subject->attach(&observer2); |
| 117 | + |
| 118 | + subject->setState(10); |
| 119 | + subject->notify(); |
| 120 | + |
| 121 | + std::cout << "Observer 1 state: " << observer1.getState() << std::endl; |
| 122 | + std::cout << "Observer 2 state: " << observer2.getState() << std::endl; |
| 123 | + |
| 124 | + return 0; |
| 125 | +} |
0 commit comments