1
- using System ;
1
+ // EN: Observer Design Pattern
2
+ //
3
+ // Intent: Define a one-to-many dependency between objects so that when one
4
+ // object changes state, all of its dependents are notified and updated
5
+ // automatically.
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
+ using System ;
2
25
using System . Collections . Generic ;
3
26
using System . Threading ;
4
27
5
28
namespace RefactoringGuru . DesignPatterns . Observer . Conceptual
6
29
{
7
30
public interface IObserver
8
31
{
9
- void update ( ISubject subject ) ;
32
+ // EN: Receive update from subject
33
+ //
34
+ // RU: Получает обновление от издателя
35
+ void Update ( ISubject subject ) ;
10
36
}
11
37
12
38
public interface ISubject
13
39
{
14
- void attach ( IObserver observer ) ;
15
-
16
- void detach ( IObserver observer ) ;
17
-
18
- void notify ( ) ;
40
+ // EN: Attach an observer to the subject.
41
+ //
42
+ // RU: Присоединяет наблюдателя к издателю.
43
+ void Attach ( IObserver observer ) ;
44
+
45
+ // EN: Detach an observer from the subject.
46
+ //
47
+ // RU: Отсоединяет наблюдателя от издателя.
48
+ void Detach ( IObserver observer ) ;
49
+
50
+ // EN: Notify all observers about an event.
51
+ //
52
+ // RU: Уведомляет всех наблюдателей о событии.
53
+ void Notify ( ) ;
19
54
}
20
55
56
+ // EN: The Subject owns some important state and notifies observers when the
57
+ // state changes.
58
+ //
59
+ // RU: Издатель владеет некоторым важным состоянием и оповещает наблюдателей о
60
+ // его изменениях.
21
61
public class Subject : ISubject
22
62
{
63
+ // EN: For the sake of simplicity, the Subject's state, essential
64
+ // to all subscribers, is stored in this variable.
65
+ //
66
+ // RU: Для удобства в этой переменной хранится состояние Издателя,
67
+ // необходимое всем подписчикам.
23
68
public int State { get ; set ; } = - 0 ;
24
69
70
+ // EN: List of subscribers. In real life, the list of subscribers
71
+ // can be stored more comprehensively (categorized by event type, etc.).
72
+ //
73
+ // RU: Список подписчиков. В реальной жизни список подписчиков
74
+ // может храниться в более подробном виде (классифицируется по типу события
75
+ // и т.д.)
25
76
private List < IObserver > _observers = new List < IObserver > ( ) ;
26
77
27
- public void attach ( IObserver observer )
78
+ // EN: The subscription management methods.
79
+ //
80
+ // RU: Методы управления подпиской.
81
+ public void Attach ( IObserver observer )
28
82
{
29
- Console . Write ( "Subject: Attached an observer.\n " ) ;
83
+ Console . WriteLine ( "Subject: Attached an observer." ) ;
30
84
this . _observers . Add ( observer ) ;
31
85
}
32
86
33
- public void detach ( IObserver observer )
87
+ public void Detach ( IObserver observer )
34
88
{
35
- foreach ( var elem in _observers )
36
- {
37
- if ( elem == observer )
38
- {
39
- _observers . Remove ( observer ) ;
40
- Console . Write ( "Subject: Detached an observer.\n " ) ;
41
- break ;
42
- }
43
- }
89
+ this . _observers . Remove ( observer ) ;
90
+ Console . WriteLine ( "Subject: Detached an observer." ) ;
44
91
}
45
92
46
- public void notify ( )
93
+ //
94
+ // EN: Trigger an update in each subscriber.
95
+ //
96
+ // RU: Запуск обновления в каждом подписчике.
97
+ ///
98
+ public void Notify ( )
47
99
{
48
- Console . Write ( "Subject: Notifying observers...\n " ) ;
100
+ Console . WriteLine ( "Subject: Notifying observers..." ) ;
49
101
50
102
foreach ( var observer in _observers )
51
103
{
52
- observer . update ( this ) ;
104
+ observer . Update ( this ) ;
53
105
}
54
106
}
55
107
56
- public void someBusinessLogic ( )
108
+ // EN: Usually, the subscription logic is only a fraction of what a Subject
109
+ // can really do. Subjects commonly hold some important business logic, that
110
+ // triggers a notification method whenever something important is about to
111
+ // happen (or after it).
112
+ //
113
+ // RU: Обычно логика подписки – только часть того, что делает Издатель.
114
+ // Издатели часто содержат некоторую важную бизнес-логику, которая запускает
115
+ // метод уведомления всякий раз, когда должно произойти что-то важное (или
116
+ // после этого).
117
+ public void SomeBusinessLogic ( )
57
118
{
58
- Console . Write ( "\n Subject: I'm doing something important.\n " ) ;
119
+ Console . WriteLine ( "\n Subject: I'm doing something important." ) ;
59
120
this . State = new Random ( ) . Next ( 0 , 10 ) ;
60
121
61
122
Thread . Sleep ( 15 ) ;
62
123
63
- Console . Write ( "Subject: My state has just changed to: " + this . State + " \n " ) ;
64
- this . notify ( ) ;
124
+ Console . WriteLine ( "Subject: My state has just changed to: " + this . State ) ;
125
+ this . Notify ( ) ;
65
126
}
66
127
}
67
128
129
+ // EN: Concrete Observers react to the updates issued by the Subject they had
130
+ // been attached to.
131
+ //
132
+ // RU: Конкретные Наблюдатели реагируют на обновления, выпущенные Издателем, к
133
+ // которому они прикреплены.
68
134
class ConcreteObserverA : IObserver
69
135
{
70
- public void update ( ISubject subject )
71
- {
72
- if ( ! ( subject is Subject ) )
73
- {
74
- return ;
75
- }
76
-
136
+ public void Update ( ISubject subject )
137
+ {
77
138
if ( ( subject as Subject ) . State < 3 )
78
139
{
79
- Console . Write ( "ConcreteObserverA: Reacted to the event.\n " ) ;
140
+ Console . WriteLine ( "ConcreteObserverA: Reacted to the event." ) ;
80
141
}
81
142
}
82
143
}
83
144
84
145
class ConcreteObserverB : IObserver
85
146
{
86
- public void update ( ISubject subject )
147
+ public void Update ( ISubject subject )
87
148
{
88
- if ( ! ( subject is Subject ) )
89
- {
90
- return ;
91
- }
92
-
93
149
if ( ( subject as Subject ) . State == 0 || ( subject as Subject ) . State >= 2 )
94
150
{
95
- Console . Write ( "ConcreteObserverB: Reacted to the event.\n " ) ;
151
+ Console . WriteLine ( "ConcreteObserverB: Reacted to the event." ) ;
96
152
}
97
153
}
98
154
}
@@ -101,19 +157,22 @@ class Client
101
157
{
102
158
public static void ClientCode ( )
103
159
{
104
- var subj = new Subject ( ) ;
105
- var o1 = new ConcreteObserverA ( ) ;
106
- subj . attach ( o1 ) ;
160
+ // EN: The client code.
161
+ //
162
+ // RU: Клиентский код.
163
+ var subject = new Subject ( ) ;
164
+ var observerA = new ConcreteObserverA ( ) ;
165
+ subject . Attach ( observerA ) ;
107
166
108
- var o2 = new ConcreteObserverB ( ) ;
109
- subj . attach ( o2 ) ;
167
+ var observerB = new ConcreteObserverB ( ) ;
168
+ subject . Attach ( observerB ) ;
110
169
111
- subj . someBusinessLogic ( ) ;
112
- subj . someBusinessLogic ( ) ;
170
+ subject . SomeBusinessLogic ( ) ;
171
+ subject . SomeBusinessLogic ( ) ;
113
172
114
- subj . detach ( o2 ) ;
173
+ subject . Detach ( observerB ) ;
115
174
116
- subj . someBusinessLogic ( ) ;
175
+ subject . SomeBusinessLogic ( ) ;
117
176
}
118
177
}
119
178
0 commit comments