improvement: EventAggregator now considers Event-Type (#1933)

* Implemented more granular registration of observers with HashMap;
Key: Event, Value: List of Observers registered for the event;

* Edited constructors and super calls of all EventEmitter extenders

* Edited constructor calls in App.java

* Edited EventEmitterTest

* Added new white walkers event, scout emits at wednesday, varys observes and emits at saturday

* Added white walkers event to KingsHandTest.java

* Varys now passes events

* Corrected some indentation levels and added curly braces to if statements

* Corrected some styling

* Switched lines in App.java,
added javadoc to registerObserver

* Fixed some indents, added param comments
This commit is contained in:
Leisterbecker 2021-12-23 19:43:36 +01:00 committed by GitHub
parent 4588e09939
commit df73d80365
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 81 additions and 30 deletions

View File

@ -49,13 +49,28 @@ public class App {
public static void main(String[] args) { public static void main(String[] args) {
var kingJoffrey = new KingJoffrey(); var kingJoffrey = new KingJoffrey();
var kingsHand = new KingsHand(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( var emitters = List.of(
kingsHand, kingsHand,
new LordBaelish(kingsHand), baelish,
new LordVarys(kingsHand), varys,
new Scout(kingsHand) scout
); );
Arrays.stream(Weekday.values()) Arrays.stream(Weekday.values())

View File

@ -31,6 +31,7 @@ import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor @RequiredArgsConstructor
public enum Event { public enum Event {
WHITE_WALKERS_SIGHTED("White walkers sighted"),
STARK_SIGHTED("Stark sighted"), STARK_SIGHTED("Stark sighted"),
WARSHIPS_APPROACHING("Warships approaching"), WARSHIPS_APPROACHING("Warships approaching"),
TRAITOR_DETECTED("Traitor detected"); TRAITOR_DETECTED("Traitor detected");

View File

@ -23,31 +23,48 @@
package com.iluwatar.event.aggregator; package com.iluwatar.event.aggregator;
import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* EventEmitter is the base class for event producers that can be observed. * EventEmitter is the base class for event producers that can be observed.
*/ */
public abstract class EventEmitter { public abstract class EventEmitter {
private final List<EventObserver> observers; private final Map<Event, List<EventObserver>> observerLists;
public EventEmitter() { public EventEmitter() {
observers = new LinkedList<>(); observerLists = new HashMap<>();
} }
public EventEmitter(EventObserver obs) { public EventEmitter(EventObserver obs, Event e) {
this(); this();
registerObserver(obs); registerObserver(obs, e);
} }
public final void registerObserver(EventObserver obs) { /**
observers.add(obs); * Registers observer for specific event in the related list.
*
* @param obs the observer that observers this emitter
* @param e the specific event for that observation occurs
* */
public final void registerObserver(EventObserver obs, Event e) {
if (!observerLists.containsKey(e)) {
observerLists.put(e, new LinkedList<>());
}
if (!observerLists.get(e).contains(obs)) {
observerLists.get(e).add(obs);
}
} }
protected void notifyObservers(Event e) { protected void notifyObservers(Event e) {
observers.forEach(obs -> obs.onEvent(e)); if (observerLists.containsKey(e)) {
observerLists
.get(e)
.forEach(observer -> observer.onEvent(e));
}
} }
public abstract void timePasses(Weekday day); public abstract void timePasses(Weekday day);

View File

@ -31,8 +31,8 @@ public class KingsHand extends EventEmitter implements EventObserver {
public KingsHand() { public KingsHand() {
} }
public KingsHand(EventObserver obs) { public KingsHand(EventObserver obs, Event e) {
super(obs); super(obs, e);
} }
@Override @Override
@ -42,6 +42,5 @@ public class KingsHand extends EventEmitter implements EventObserver {
@Override @Override
public void timePasses(Weekday day) { public void timePasses(Weekday day) {
// NOP
} }
} }

View File

@ -31,8 +31,8 @@ public class LordBaelish extends EventEmitter {
public LordBaelish() { public LordBaelish() {
} }
public LordBaelish(EventObserver obs) { public LordBaelish(EventObserver obs, Event e) {
super(obs); super(obs, e);
} }
@Override @Override

View File

@ -23,16 +23,19 @@
package com.iluwatar.event.aggregator; package com.iluwatar.event.aggregator;
import lombok.extern.slf4j.Slf4j;
/** /**
* LordVarys produces events. * LordVarys produces events.
*/ */
public class LordVarys extends EventEmitter { @Slf4j
public class LordVarys extends EventEmitter implements EventObserver {
public LordVarys() { public LordVarys() {
} }
public LordVarys(EventObserver obs) { public LordVarys(EventObserver obs, Event e) {
super(obs); super(obs, e);
} }
@Override @Override
@ -41,4 +44,10 @@ public class LordVarys extends EventEmitter {
notifyObservers(Event.TRAITOR_DETECTED); notifyObservers(Event.TRAITOR_DETECTED);
} }
} }
@Override
public void onEvent(Event e) {
notifyObservers(e);
}
} }

View File

@ -31,8 +31,8 @@ public class Scout extends EventEmitter {
public Scout() { public Scout() {
} }
public Scout(EventObserver obs) { public Scout(EventObserver obs, Event e) {
super(obs); super(obs, e);
} }
@Override @Override
@ -40,5 +40,8 @@ public class Scout extends EventEmitter {
if (day == Weekday.TUESDAY) { if (day == Weekday.TUESDAY) {
notifyObservers(Event.WARSHIPS_APPROACHING); notifyObservers(Event.WARSHIPS_APPROACHING);
} }
if (day == Weekday.WEDNESDAY) {
notifyObservers(Event.WHITE_WALKERS_SIGHTED);
}
} }
} }

View File

@ -31,6 +31,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.verifyZeroInteractions;
import java.util.Objects; import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -46,7 +47,7 @@ abstract class EventEmitterTest<E extends EventEmitter> {
/** /**
* Factory used to create a new instance of the test object with a default observer * Factory used to create a new instance of the test object with a default observer
*/ */
private final Function<EventObserver, E> factoryWithDefaultObserver; private final BiFunction<EventObserver, Event, E> factoryWithDefaultObserver;
/** /**
* Factory used to create a new instance of the test object without passing a default observer * Factory used to create a new instance of the test object without passing a default observer
@ -67,7 +68,7 @@ abstract class EventEmitterTest<E extends EventEmitter> {
* Create a new event emitter test, using the given test object factories, special day and event * Create a new event emitter test, using the given test object factories, special day and event
*/ */
EventEmitterTest(final Weekday specialDay, final Event event, EventEmitterTest(final Weekday specialDay, final Event event,
final Function<EventObserver, E> factoryWithDefaultObserver, final BiFunction<EventObserver, Event, E> factoryWithDefaultObserver,
final Supplier<E> factoryWithoutDefaultObserver) { final Supplier<E> factoryWithoutDefaultObserver) {
this.specialDay = specialDay; this.specialDay = specialDay;
@ -129,8 +130,8 @@ abstract class EventEmitterTest<E extends EventEmitter> {
final var observer2 = mock(EventObserver.class); final var observer2 = mock(EventObserver.class);
final var emitter = this.factoryWithoutDefaultObserver.get(); final var emitter = this.factoryWithoutDefaultObserver.get();
emitter.registerObserver(observer1); emitter.registerObserver(observer1, event);
emitter.registerObserver(observer2); emitter.registerObserver(observer2, event);
testAllDays(specialDay, event, emitter, observer1, observer2); testAllDays(specialDay, event, emitter, observer1, observer2);
} }
@ -146,9 +147,9 @@ abstract class EventEmitterTest<E extends EventEmitter> {
final var observer1 = mock(EventObserver.class); final var observer1 = mock(EventObserver.class);
final var observer2 = mock(EventObserver.class); final var observer2 = mock(EventObserver.class);
final var emitter = this.factoryWithDefaultObserver.apply(defaultObserver); final var emitter = this.factoryWithDefaultObserver.apply(defaultObserver, event);
emitter.registerObserver(observer1); emitter.registerObserver(observer1, event);
emitter.registerObserver(observer2); emitter.registerObserver(observer2, event);
testAllDays(specialDay, event, emitter, defaultObserver, observer1, observer2); testAllDays(specialDay, event, emitter, defaultObserver, observer1, observer2);
} }

View File

@ -55,7 +55,11 @@ class KingsHandTest extends EventEmitterTest<KingsHand> {
@Test @Test
void testPassThrough() throws Exception { void testPassThrough() throws Exception {
final var observer = mock(EventObserver.class); final var observer = mock(EventObserver.class);
final var kingsHand = new KingsHand(observer); final var kingsHand = new KingsHand();
kingsHand.registerObserver(observer, Event.STARK_SIGHTED);
kingsHand.registerObserver(observer, Event.WARSHIPS_APPROACHING);
kingsHand.registerObserver(observer, Event.TRAITOR_DETECTED);
kingsHand.registerObserver(observer, Event.WHITE_WALKERS_SIGHTED);
// The kings hand should not pass any events before he received one // The kings hand should not pass any events before he received one
verifyZeroInteractions(observer); verifyZeroInteractions(observer);

View File

@ -34,7 +34,9 @@ class ScoutTest extends EventEmitterTest<Scout> {
* Create a new test instance, using the correct object factory * Create a new test instance, using the correct object factory
*/ */
public ScoutTest() { public ScoutTest() {
super(Weekday.TUESDAY, Event.WARSHIPS_APPROACHING, Scout::new, Scout::new);
super(Weekday.TUESDAY, Event.WARSHIPS_APPROACHING, Scout::new, Scout::new);
} }
} }