2015-08-13 23:54:40 +02:00
|
|
|
---
|
|
|
|
layout: pattern
|
|
|
|
title: Event Aggregator
|
|
|
|
folder: event-aggregator
|
2015-08-15 18:03:05 +02:00
|
|
|
permalink: /patterns/event-aggregator/
|
2015-08-20 21:40:07 +02:00
|
|
|
categories: Structural
|
2021-05-19 10:49:05 -06:00
|
|
|
language: en
|
2015-12-28 15:52:44 +02:00
|
|
|
tags:
|
2016-07-21 09:27:48 +03:00
|
|
|
- Reactive
|
2015-08-13 23:54:40 +02:00
|
|
|
---
|
|
|
|
|
2022-01-06 18:43:16 +02:00
|
|
|
## Name
|
|
|
|
|
|
|
|
Event Aggregator
|
|
|
|
|
2016-01-03 21:14:30 +01:00
|
|
|
## Intent
|
|
|
|
A system with lots of objects can lead to complexities when a
|
2015-08-13 23:54:40 +02:00
|
|
|
client wants to subscribe to events. The client has to find and register for
|
|
|
|
each object individually, if each object has multiple events then each event
|
|
|
|
requires a separate subscription. An Event Aggregator acts as a single source
|
|
|
|
of events for many objects. It registers for all the events of the many objects
|
|
|
|
allowing clients to register with just the aggregator.
|
|
|
|
|
2022-01-06 18:43:16 +02:00
|
|
|
## Explanation
|
|
|
|
|
|
|
|
Real-world example
|
|
|
|
|
|
|
|
> King Joffrey sits on the iron throne and rules the seven kingdoms of Westeros. He receives most
|
|
|
|
> of his critical information from King's Hand, the second in command. King's hand has many
|
|
|
|
> close advisors himself, feeding him with relevant information about events occurring in the
|
|
|
|
> kingdom.
|
|
|
|
|
|
|
|
In Plain Words
|
|
|
|
|
|
|
|
> Event Aggregator is an event mediator that collects events from multiple sources and delivers
|
|
|
|
> them to registered observers.
|
|
|
|
|
|
|
|
**Programmatic Example**
|
|
|
|
|
|
|
|
In our programmatic example, we demonstrate the implementation of an event aggregator pattern. Some of
|
|
|
|
the objects are event listeners, some are event emitters, and the event aggregator does both.
|
|
|
|
|
|
|
|
```java
|
|
|
|
public interface EventObserver {
|
|
|
|
void onEvent(Event e);
|
|
|
|
}
|
|
|
|
|
|
|
|
public abstract class EventEmitter {
|
|
|
|
|
|
|
|
private final Map<Event, List<EventObserver>> observerLists;
|
|
|
|
|
|
|
|
public EventEmitter() {
|
|
|
|
observerLists = new HashMap<>();
|
|
|
|
}
|
|
|
|
|
|
|
|
public final void registerObserver(EventObserver obs, Event e) {
|
|
|
|
...
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void notifyObservers(Event e) {
|
|
|
|
...
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
`KingJoffrey` is listening to events from `KingsHand`.
|
|
|
|
|
|
|
|
```java
|
|
|
|
@Slf4j
|
|
|
|
public class KingJoffrey implements EventObserver {
|
|
|
|
@Override
|
|
|
|
public void onEvent(Event e) {
|
|
|
|
LOGGER.info("Received event from the King's Hand: {}", e.toString());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
`KingsHand` is listening to events from his subordinates `LordBaelish`, `LordVarys`, and `Scout`.
|
|
|
|
Whatever he hears from them, he delivers to `KingJoffrey`.
|
|
|
|
|
|
|
|
```java
|
|
|
|
public class KingsHand extends EventEmitter implements EventObserver {
|
|
|
|
|
|
|
|
public KingsHand() {
|
|
|
|
}
|
|
|
|
|
|
|
|
public KingsHand(EventObserver obs, Event e) {
|
|
|
|
super(obs, e);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onEvent(Event e) {
|
|
|
|
notifyObservers(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
For example, `LordVarys` finds a traitor every Sunday and notifies the `KingsHand`.
|
|
|
|
|
|
|
|
```java
|
|
|
|
@Slf4j
|
|
|
|
public class LordVarys extends EventEmitter implements EventObserver {
|
|
|
|
@Override
|
|
|
|
public void timePasses(Weekday day) {
|
|
|
|
if (day == Weekday.SATURDAY) {
|
|
|
|
notifyObservers(Event.TRAITOR_DETECTED);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
The following snippet demonstrates how the objects are constructed and wired together.
|
|
|
|
|
|
|
|
```java
|
|
|
|
var kingJoffrey = new KingJoffrey();
|
|
|
|
|
|
|
|
var kingsHand = new KingsHand();
|
|
|
|
kingsHand.registerObserver(kingJoffrey, Event.TRAITOR_DETECTED);
|
|
|
|
kingsHand.registerObserver(kingJoffrey, Event.STARK_SIGHTED);
|
|
|
|
kingsHand.registerObserver(kingJoffrey, Event.WARSHIPS_APPROACHING);
|
|
|
|
kingsHand.registerObserver(kingJoffrey, Event.WHITE_WALKERS_SIGHTED);
|
|
|
|
|
|
|
|
var varys = new LordVarys();
|
|
|
|
varys.registerObserver(kingsHand, Event.TRAITOR_DETECTED);
|
|
|
|
varys.registerObserver(kingsHand, Event.WHITE_WALKERS_SIGHTED);
|
|
|
|
|
|
|
|
var scout = new Scout();
|
|
|
|
scout.registerObserver(kingsHand, Event.WARSHIPS_APPROACHING);
|
|
|
|
scout.registerObserver(varys, Event.WHITE_WALKERS_SIGHTED);
|
|
|
|
|
|
|
|
var baelish = new LordBaelish(kingsHand, Event.STARK_SIGHTED);
|
|
|
|
|
|
|
|
var emitters = List.of(
|
|
|
|
kingsHand,
|
|
|
|
baelish,
|
|
|
|
varys,
|
|
|
|
scout
|
|
|
|
);
|
|
|
|
|
|
|
|
Arrays.stream(Weekday.values())
|
|
|
|
.<Consumer<? super EventEmitter>>map(day -> emitter -> emitter.timePasses(day))
|
|
|
|
.forEachOrdered(emitters::forEach);
|
|
|
|
```
|
|
|
|
|
|
|
|
The console output after running the example.
|
|
|
|
|
|
|
|
```
|
|
|
|
18:21:52.955 [main] INFO com.iluwatar.event.aggregator.KingJoffrey - Received event from the King's Hand: Warships approaching
|
|
|
|
18:21:52.960 [main] INFO com.iluwatar.event.aggregator.KingJoffrey - Received event from the King's Hand: White walkers sighted
|
|
|
|
18:21:52.960 [main] INFO com.iluwatar.event.aggregator.KingJoffrey - Received event from the King's Hand: Stark sighted
|
|
|
|
18:21:52.960 [main] INFO com.iluwatar.event.aggregator.KingJoffrey - Received event from the King's Hand: Traitor detected
|
|
|
|
```
|
|
|
|
|
2019-12-07 20:01:13 +02:00
|
|
|
## Class diagram
|
2015-08-13 23:54:40 +02:00
|
|
|

|
|
|
|
|
2016-01-03 21:14:30 +01:00
|
|
|
## Applicability
|
|
|
|
Use the Event Aggregator pattern when
|
2015-08-13 23:54:40 +02:00
|
|
|
|
|
|
|
* Event Aggregator is a good choice when you have lots of objects that are
|
|
|
|
potential event sources. Rather than have the observer deal with registering
|
|
|
|
with them all, you can centralize the registration logic to the Event
|
2022-01-06 18:43:16 +02:00
|
|
|
Aggregator. As well as simplifying registration, an Event Aggregator also
|
2015-08-15 18:03:05 +02:00
|
|
|
simplifies the memory management issues in using observers.
|
2015-09-03 18:17:07 +05:30
|
|
|
|
2022-01-06 18:43:16 +02:00
|
|
|
## Related patterns
|
|
|
|
|
|
|
|
* [Observer](https://java-design-patterns.com/patterns/observer/)
|
|
|
|
|
2016-01-03 21:14:30 +01:00
|
|
|
## Credits
|
2015-09-03 18:17:07 +05:30
|
|
|
|
|
|
|
* [Martin Fowler - Event Aggregator](http://martinfowler.com/eaaDev/EventAggregator.html)
|