Skip to content

Commit ad7681f

Browse files
committed
add Observer pattern
1 parent a5a7289 commit ad7681f

File tree

2 files changed

+136
-0
lines changed

2 files changed

+136
-0
lines changed

observer/Observer.cpp

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
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+
}

observer/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
## Observer
2+
3+
Observer defines a one-to-many dependency between objects so that when one object
4+
changes state, all its dependents are notified and updated automatically. The pattern
5+
has behavioral purpose and applies to the objects.
6+
7+
### When to use
8+
9+
* when an abstraction has two aspects, one dependent on the other
10+
* when a change to one object requires changing others, and you don't know how many objects need to be changed
11+
* when an object should be able to notify other objects without making assumptions about who these objects are

0 commit comments

Comments
 (0)