Last active
March 25, 2020 10:15
-
-
Save jakzal/554049e89791e859978916263ed52589 to your computer and use it in GitHub Desktop.
EventBus implementation in Kotlin
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package pl.zalas.eventbus | |
interface EventBus<in E> { | |
fun publish(event: E) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package pl.zalas.eventbus | |
import kotlin.reflect.KClass | |
class SimpleEventBus<E : Any> : EventBus<E> { | |
private val subscribers = mutableMapOf<KClass<*>, List<Subscriber<*>>>() | |
override fun publish(event: E) { | |
subscribers.filter { it.key.isInstance(event) } | |
.flatMap { it.value } | |
.forEach { | |
@Suppress("UNCHECKED_CAST") | |
(it as Subscriber<E>)(event) | |
} | |
} | |
inline fun <reified T : E> register(subscriber: Subscriber<T>) { | |
register(T::class, subscriber) | |
} | |
fun <T : E> register(type: KClass<T>, subscriber: Subscriber<T>) { | |
val existing = subscribers.getOrDefault(type, emptyList()) | |
subscribers[type] = existing + subscriber | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package pl.zalas.eventbus | |
import org.junit.jupiter.api.Assertions.assertEquals | |
import org.junit.jupiter.api.Test | |
import java.util.* | |
class SimpleEventBusTests { | |
interface TestEvent | |
data class FooEvent(val id: UUID = UUID.randomUUID(), val details: String = "foo") : TestEvent | |
data class BarEvent(val id: UUID = UUID.randomUUID(), val count: Int = 100) : TestEvent | |
class TestEventSubscriber(val tracker: EventTracker) : Subscriber<TestEvent> { | |
override fun invoke(event: TestEvent) { | |
tracker.register("test", event) | |
} | |
} | |
class FooEventSubscriber(val tracker: EventTracker) : Subscriber<FooEvent> { | |
override fun invoke(event: FooEvent) { | |
tracker.register("foo", event) | |
} | |
} | |
class BarEventSubscriber(val tracker: EventTracker) : Subscriber<BarEvent> { | |
override fun invoke(event: BarEvent) { | |
tracker.register("bar", event) | |
} | |
} | |
class EventTracker : HashMap<String, List<TestEvent>>() { | |
fun register(name: String, event: TestEvent) { | |
val existing = getOrDefault(name, emptyList()) | |
put(name, existing + event) | |
} | |
} | |
@Test | |
fun `it calls the registered subscribers according to the event type`() { | |
val tracker = EventTracker() | |
val eventBus = SimpleEventBus<TestEvent>() | |
eventBus.register(TestEventSubscriber(tracker)) | |
eventBus.register(FooEventSubscriber(tracker)) | |
eventBus.register(BarEventSubscriber(tracker)) | |
val foo = FooEvent() | |
val bar = BarEvent() | |
eventBus.publish(foo) | |
eventBus.publish(bar) | |
assertEquals(listOf(foo, bar), tracker["test"]) | |
assertEquals(listOf(foo), tracker["foo"]) | |
assertEquals(listOf(bar), tracker["bar"]) | |
} | |
@Test | |
fun `it register multiple subscribers of the same type`() { | |
val tracker = EventTracker() | |
val eventBus = SimpleEventBus<TestEvent>() | |
eventBus.register(FooEventSubscriber(tracker)) | |
eventBus.register(FooEventSubscriber(tracker)) | |
eventBus.register(FooEventSubscriber(tracker)) | |
val foo = FooEvent() | |
eventBus.publish(foo) | |
assertEquals(listOf(foo, foo, foo), tracker["foo"]) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package pl.zalas.eventbus | |
interface Subscriber<in E>: (E) -> Unit |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment