9
9
- Reactive
10
10
---
11
11
12
+ ## Name
13
+
14
+ Event Aggregator
15
+
12
16
## Intent
13
17
A system with lots of objects can lead to complexities when a
14
18
client wants to subscribe to events. The client has to find and register for
@@ -17,6 +21,136 @@ requires a separate subscription. An Event Aggregator acts as a single source
17
21
of events for many objects. It registers for all the events of the many objects
18
22
allowing clients to register with just the aggregator.
19
23
24
+ ## Explanation
25
+
26
+ Real-world example
27
+
28
+ > King Joffrey sits on the iron throne and rules the seven kingdoms of Westeros. He receives most
29
+ > of his critical information from King's Hand, the second in command. King's hand has many
30
+ > close advisors himself, feeding him with relevant information about events occurring in the
31
+ > kingdom.
32
+
33
+ In Plain Words
34
+
35
+ > Event Aggregator is an event mediator that collects events from multiple sources and delivers
36
+ > them to registered observers.
37
+
38
+ ** Programmatic Example**
39
+
40
+ In our programmatic example, we demonstrate the implementation of an event aggregator pattern. Some of
41
+ the objects are event listeners, some are event emitters, and the event aggregator does both.
42
+
43
+ ``` java
44
+ public interface EventObserver {
45
+ void onEvent (Event e );
46
+ }
47
+
48
+ public abstract class EventEmitter {
49
+
50
+ private final Map<Event , List<EventObserver > > observerLists;
51
+
52
+ public EventEmitter () {
53
+ observerLists = new HashMap<> ();
54
+ }
55
+
56
+ public final void registerObserver (EventObserver obs , Event e ) {
57
+ ...
58
+ }
59
+
60
+ protected void notifyObservers (Event e ) {
61
+ ...
62
+ }
63
+ }
64
+ ```
65
+
66
+ ` KingJoffrey ` is listening to events from ` KingsHand ` .
67
+
68
+ ``` java
69
+ @Slf4j
70
+ public class KingJoffrey implements EventObserver {
71
+ @Override
72
+ public void onEvent (Event e ) {
73
+ LOGGER . info(" Received event from the King's Hand: {}" , e. toString());
74
+ }
75
+ }
76
+ ```
77
+
78
+ ` KingsHand ` is listening to events from his subordinates ` LordBaelish ` , ` LordVarys ` , and ` Scout ` .
79
+ Whatever he hears from them, he delivers to ` KingJoffrey ` .
80
+
81
+ ``` java
82
+ public class KingsHand extends EventEmitter implements EventObserver {
83
+
84
+ public KingsHand () {
85
+ }
86
+
87
+ public KingsHand (EventObserver obs , Event e ) {
88
+ super (obs, e);
89
+ }
90
+
91
+ @Override
92
+ public void onEvent (Event e ) {
93
+ notifyObservers(e);
94
+ }
95
+ }
96
+ ```
97
+
98
+ For example, ` LordVarys ` finds a traitor every Sunday and notifies the ` KingsHand ` .
99
+
100
+ ``` java
101
+ @Slf4j
102
+ public class LordVarys extends EventEmitter implements EventObserver {
103
+ @Override
104
+ public void timePasses (Weekday day ) {
105
+ if (day == Weekday . SATURDAY ) {
106
+ notifyObservers(Event . TRAITOR_DETECTED );
107
+ }
108
+ }
109
+ }
110
+ ```
111
+
112
+ The following snippet demonstrates how the objects are constructed and wired together.
113
+
114
+ ``` java
115
+ var kingJoffrey = new KingJoffrey ();
116
+
117
+ var kingsHand = new KingsHand ();
118
+ kingsHand. registerObserver(kingJoffrey, Event . TRAITOR_DETECTED );
119
+ kingsHand. registerObserver(kingJoffrey, Event . STARK_SIGHTED );
120
+ kingsHand. registerObserver(kingJoffrey, Event . WARSHIPS_APPROACHING );
121
+ kingsHand. registerObserver(kingJoffrey, Event . WHITE_WALKERS_SIGHTED );
122
+
123
+ var varys = new LordVarys ();
124
+ varys. registerObserver(kingsHand, Event . TRAITOR_DETECTED );
125
+ varys. registerObserver(kingsHand, Event . WHITE_WALKERS_SIGHTED );
126
+
127
+ var scout = new Scout ();
128
+ scout. registerObserver(kingsHand, Event . WARSHIPS_APPROACHING );
129
+ scout. registerObserver(varys, Event . WHITE_WALKERS_SIGHTED );
130
+
131
+ var baelish = new LordBaelish (kingsHand, Event . STARK_SIGHTED );
132
+
133
+ var emitters = List . of(
134
+ kingsHand,
135
+ baelish,
136
+ varys,
137
+ scout
138
+ );
139
+
140
+ Arrays . stream(Weekday . values())
141
+ . < Consumer<? super EventEmitter > > map(day - > emitter - > emitter. timePasses(day))
142
+ .forEachOrdered(emitters:: forEach);
143
+ ```
144
+
145
+ The console output after running the example.
146
+
147
+ ```
148
+ 18:21:52.955 [main] INFO com.iluwatar.event.aggregator.KingJoffrey - Received event from the King's Hand: Warships approaching
149
+ 18:21:52.960 [main] INFO com.iluwatar.event.aggregator.KingJoffrey - Received event from the King's Hand: White walkers sighted
150
+ 18:21:52.960 [main] INFO com.iluwatar.event.aggregator.KingJoffrey - Received event from the King's Hand: Stark sighted
151
+ 18:21:52.960 [main] INFO com.iluwatar.event.aggregator.KingJoffrey - Received event from the King's Hand: Traitor detected
152
+ ```
153
+
20
154
## Class diagram
21
155
![ alt text] ( ./etc/classes.png " Event Aggregator ")
22
156
@@ -26,9 +160,13 @@ Use the Event Aggregator pattern when
26
160
* Event Aggregator is a good choice when you have lots of objects that are
27
161
potential event sources. Rather than have the observer deal with registering
28
162
with them all, you can centralize the registration logic to the Event
29
- Aggregator. As well as simplifying registration, a Event Aggregator also
163
+ Aggregator. As well as simplifying registration, an Event Aggregator also
30
164
simplifies the memory management issues in using observers.
31
165
166
+ ## Related patterns
167
+
168
+ * [ Observer] ( https://java-design-patterns.com/patterns/observer/ )
169
+
32
170
## Credits
33
171
34
172
* [ Martin Fowler - Event Aggregator] ( http://martinfowler.com/eaaDev/EventAggregator.html )
0 commit comments