forked from Volodichev/patterns
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathobserver.py
More file actions
135 lines (101 loc) · 4.14 KB
/
observer.py
File metadata and controls
135 lines (101 loc) · 4.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
from __future__ import annotations
from abc import ABC, abstractmethod
from random import randrange
from typing import List
class Subject(ABC):
"""
Интферфейс издателя объявляет набор методов для управлениями подписчиками.
"""
@abstractmethod
def attach(self, observer: Observer) -> None:
"""
Присоединяет наблюдателя к издателю.
"""
pass
@abstractmethod
def detach(self, observer: Observer) -> None:
"""
Отсоединяет наблюдателя от издателя.
"""
pass
@abstractmethod
def notify(self) -> None:
"""
Уведомляет всех наблюдателей о событии.
"""
pass
class ConcreteSubject(Subject):
"""
Издатель владеет некоторым важным состоянием и оповещает наблюдателей о его
изменениях.
"""
_state: int = None
"""
Для удобства в этой переменной хранится состояние Издателя, необходимое всем
подписчикам.
"""
_observers: List[Observer] = []
"""
Список подписчиков. В реальной жизни список подписчиков может храниться в
более подробном виде (классифицируется по типу события и т.д.)
"""
def attach(self, observer: Observer) -> None:
print("Subject: Attached an observer.")
self._observers.append(observer)
def detach(self, observer: Observer) -> None:
self._observers.remove(observer)
"""
Методы управления подпиской.
"""
def notify(self) -> None:
"""
Запуск обновления в каждом подписчике.
"""
print("Subject: Notifying observers...")
for observer in self._observers:
observer.update(self)
def some_business_logic(self) -> None:
"""
Обычно логика подписки – только часть того, что делает Издатель.
Издатели часто содержат некоторую важную бизнес-логику, которая
запускает метод уведомления всякий раз, когда должно произойти что-то
важное (или после этого).
"""
print("\nSubject: I'm doing something important.")
self._state = randrange(0, 10)
print(f"Subject: My state has just changed to: {self._state}")
self.notify()
class Observer(ABC):
"""
Интерфейс Наблюдателя объявляет метод уведомления, который издатели
используют для оповещения своих подписчиков.
"""
@abstractmethod
def update(self, subject: Subject) -> None:
"""
Получить обновление от субъекта.
"""
pass
"""
Конкретные Наблюдатели реагируют на обновления, выпущенные Издателем, к которому
они прикреплены.
"""
class ConcreteObserverA(Observer):
def update(self, subject: Subject) -> None:
if subject._state < 3:
print("ConcreteObserverA: Reacted to the event")
class ConcreteObserverB(Observer):
def update(self, subject: Subject) -> None:
if subject._state == 0 or subject._state >= 2:
print("ConcreteObserverB: Reacted to the event")
if __name__ == "__main__":
# Клиентский код.
subject = ConcreteSubject()
observer_a = ConcreteObserverA()
subject.attach(observer_a)
observer_b = ConcreteObserverB()
subject.attach(observer_b)
subject.some_business_logic()
subject.some_business_logic()
subject.detach(observer_a)
subject.some_business_logic()