|
| 1 | +/** |
| 2 | + * EN: Observer Design Pattern |
| 3 | + * |
| 4 | + * Intent: Lets you define a subscription mechanism to notify multiple objects |
| 5 | + * about any events that happen to the object they're observing. |
| 6 | + * |
| 7 | + * Note that there's a lot of different terms with similar meaning associated |
| 8 | + * with this pattern. Just remember that the Subject is also called the |
| 9 | + * Publisher and the Observer is often called the Subscriber and vice versa. |
| 10 | + * Also the verbs "observe", "listen" or "track" usually mean the same thing. |
| 11 | + * |
| 12 | + * RU: Паттерн Наблюдатель |
| 13 | + * |
| 14 | + * Назначение: Создаёт механизм подписки, позволяющий одним объектам следить и |
| 15 | + * реагировать на события, происходящие в других объектах. |
| 16 | + * |
| 17 | + * Обратите внимание, что существует множество различных терминов с похожими |
| 18 | + * значениями, связанных с этим паттерном. Просто помните, что Субъекта также |
| 19 | + * называют Издателем, а Наблюдателя часто называют Подписчиком и наоборот. |
| 20 | + * Также глаголы «наблюдать», «слушать» или «отслеживать» обычно означают одно и |
| 21 | + * то же. |
| 22 | + */ |
| 23 | + |
| 24 | +#include <list> |
| 25 | +#include <string> |
| 26 | +#include <iostream> |
| 27 | + |
| 28 | +class IObserver |
| 29 | +{ |
| 30 | + |
| 31 | +public: |
| 32 | + virtual ~IObserver(){}; |
| 33 | + virtual void Update(const std::string &message_from_subject) = 0; |
| 34 | +}; |
| 35 | + |
| 36 | +class ISubject |
| 37 | +{ |
| 38 | +public: |
| 39 | + virtual ~ISubject(){}; |
| 40 | + virtual void Attach(IObserver *observer) = 0; |
| 41 | + virtual void Detach(IObserver *observer) = 0; |
| 42 | + virtual void Notify() = 0; |
| 43 | +}; |
| 44 | + |
| 45 | +/** |
| 46 | + * EN: The Subject owns some important state and notifies observers when the |
| 47 | + * state changes. |
| 48 | + * |
| 49 | + * RU: Издатель владеет некоторым важным состоянием и оповещает наблюдателей о |
| 50 | + * его изменениях. |
| 51 | + */ |
| 52 | + |
| 53 | +class Subject : public ISubject |
| 54 | +{ |
| 55 | + |
| 56 | +public: |
| 57 | + virtual ~Subject() |
| 58 | + { |
| 59 | + std::cout << "Goodbye, I was the Subject.\n"; |
| 60 | + } |
| 61 | + |
| 62 | + /** |
| 63 | + * EN: The subscription management methods. |
| 64 | + * |
| 65 | + * RU: Методы управления подпиской. |
| 66 | + */ |
| 67 | + void Attach(IObserver *observer) override |
| 68 | + { |
| 69 | + list_observer_.push_back(observer); |
| 70 | + } |
| 71 | + void Detach(IObserver *observer) override |
| 72 | + { |
| 73 | + list_observer_.remove(observer); |
| 74 | + } |
| 75 | + void Notify() override |
| 76 | + { |
| 77 | + std::list<IObserver *>::iterator iterator = list_observer_.begin(); |
| 78 | + HowManyObserver(); |
| 79 | + while (iterator != list_observer_.end()) |
| 80 | + { |
| 81 | + (*iterator)->Update(message_); |
| 82 | + ++iterator; |
| 83 | + } |
| 84 | + } |
| 85 | + |
| 86 | + void CreateMessage(std::string message = "Empty") |
| 87 | + { |
| 88 | + this->message_ = message; |
| 89 | + Notify(); |
| 90 | + } |
| 91 | + void HowManyObserver() |
| 92 | + { |
| 93 | + std::cout << "There are " << list_observer_.size() << " observers in the list.\n"; |
| 94 | + } |
| 95 | + |
| 96 | + /** |
| 97 | + * EN: Usually, the subscription logic is only a fraction of what a Subject |
| 98 | + * can really do. Subjects commonly hold some important business logic, that |
| 99 | + * triggers a notification method whenever something important is about to |
| 100 | + * happen (or after it). |
| 101 | + * |
| 102 | + * RU: Обычно логика подписки – только часть того, что делает Издатель. |
| 103 | + * Издатели часто содержат некоторую важную бизнес-логику, которая запускает |
| 104 | + * метод уведомления всякий раз, когда должно произойти что-то важное (или |
| 105 | + * после этого). |
| 106 | + */ |
| 107 | + void SomeBusinessLogic() |
| 108 | + { |
| 109 | + this->message_ = "change message message"; |
| 110 | + Notify(); |
| 111 | + std::cout << "I'm about to do some thing important\n"; |
| 112 | + } |
| 113 | + |
| 114 | +private: |
| 115 | + std::list<IObserver *> list_observer_; |
| 116 | + std::string message_; |
| 117 | +}; |
| 118 | + |
| 119 | +class Observer : public IObserver |
| 120 | +{ |
| 121 | + |
| 122 | +public: |
| 123 | + Observer(Subject &subject) : subject_(subject) |
| 124 | + { |
| 125 | + this->subject_.Attach(this); |
| 126 | + std::cout << "Hi, I'm the Observer \"" << ++Observer::static_number_ << "\".\n"; |
| 127 | + this->number_ = Observer::static_number_; |
| 128 | + } |
| 129 | + virtual ~Observer() |
| 130 | + { |
| 131 | + std::cout << "Goodbye, I was the Observer \"" << this->number_ << "\".\n"; |
| 132 | + } |
| 133 | + |
| 134 | + void Update(const std::string &message_from_subject) override |
| 135 | + { |
| 136 | + message_from_subject_ = message_from_subject; |
| 137 | + PrintInfo(); |
| 138 | + } |
| 139 | + void RemoveMeFromTheList() |
| 140 | + { |
| 141 | + subject_.Detach(this); |
| 142 | + std::cout << "Observer \"" << number_ << "\" removed from the list.\n"; |
| 143 | + } |
| 144 | + void PrintInfo() |
| 145 | + { |
| 146 | + std::cout << "Observer \"" << this->number_ << "\": a new message is available --> " << this->message_from_subject_ << "\n"; |
| 147 | + } |
| 148 | + |
| 149 | +private: |
| 150 | + std::string message_from_subject_; |
| 151 | + Subject &subject_; |
| 152 | + static int static_number_; |
| 153 | + int number_; |
| 154 | +}; |
| 155 | + |
| 156 | +int Observer::static_number_ = 0; |
| 157 | + |
| 158 | +void ClientCode() |
| 159 | +{ |
| 160 | + Subject *subject = new Subject; |
| 161 | + Observer *observer1 = new Observer(*subject); |
| 162 | + Observer *observer2 = new Observer(*subject); |
| 163 | + Observer *observer3 = new Observer(*subject); |
| 164 | + Observer *observer4; |
| 165 | + Observer *observer5; |
| 166 | + |
| 167 | + subject->CreateMessage("Hello World! :D"); |
| 168 | + observer3->RemoveMeFromTheList(); |
| 169 | + |
| 170 | + subject->CreateMessage("The weather is hot today! :p"); |
| 171 | + observer4 = new Observer(*subject); |
| 172 | + |
| 173 | + observer2->RemoveMeFromTheList(); |
| 174 | + observer5 = new Observer(*subject); |
| 175 | + |
| 176 | + subject->CreateMessage("My new car is great! ;)"); |
| 177 | + observer5->RemoveMeFromTheList(); |
| 178 | + |
| 179 | + observer4->RemoveMeFromTheList(); |
| 180 | + observer1->RemoveMeFromTheList(); |
| 181 | + |
| 182 | + delete observer5; |
| 183 | + delete observer4; |
| 184 | + delete observer3; |
| 185 | + delete observer2; |
| 186 | + delete observer1; |
| 187 | + delete subject; |
| 188 | +} |
| 189 | + |
| 190 | +int main() |
| 191 | +{ |
| 192 | + ClientCode(); |
| 193 | + return 0; |
| 194 | +} |
0 commit comments