diff --git a/observer/Observer.cpp b/observer/Observer.cpp new file mode 100644 index 0000000..9d38536 --- /dev/null +++ b/observer/Observer.cpp @@ -0,0 +1,125 @@ +/* + * 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 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(int state) + : observer_state(state) {} + + 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: + void attach(Observer *observer) { + observers.push_back(observer); + } + + void detach(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(int s) = 0; + // ... + +private: + std::vector observers; + // ... +}; + +/* + * Concrete Subject + * stores state that should stay consistent with the subject's + */ +class ConcreteSubject : public Subject { +public: + int getState() { + return subject_state; + } + + void setState(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; + + return 0; +} diff --git a/observer/README.md b/observer/README.md new file mode 100644 index 0000000..03b8749 --- /dev/null +++ b/observer/README.md @@ -0,0 +1,11 @@ +## Observer + +Observer defines a one-to-many dependency between objects so that when one object +changes state, all its dependents are notified and updated automatically. The pattern +has behavioral purpose and applies to the objects. + +### When to use + +* when an abstraction has two aspects, one dependent on the other +* when a change to one object requires changing others, and you don't know how many objects need to be changed +* when an object should be able to notify other objects without making assumptions about who these objects are \ No newline at end of file