I have the following classes:
interface Event
interface NotificationEvent : Event
data class InviteEvent(val userId: Long, val inviteeId: Long) : NotificationEvent
Event
represents a generic event
NotificationEvent
represents an event that trigger a notification
InviteEvent
represents an implementation of NotificationEvent
I would write a code that reacts to notification events, writing handlers for every type of event.
Accordingly to "Open-close" principle, I'd like to avoid to edit some existing classes to handle new types of event (i.e. avoid the hell switch case). The idea that I came up with was creating the following classes:
abstract class NotificationEventHandler<T : NotificationEvent> {
fun handle(notificationEvent: NotificationEvent) {
@Suppress("UNCHECKED_CAST")
if (isSupported(notificationEvent)) {
handleInternal(notificationEvent as T)
}
}
protected abstract fun isSupported(notificationEvent: NotificationEvent): Boolean
protected abstract fun handleInternal(notificationEvent: T)
}
@Component
class InviteEventHandler : NotificationEventHandler<InviteEvent>() {
override fun isSupported(notificationEvent: NotificationEvent) =
notificationEvent is InviteEvent
override fun handleInternal(notificationEvent: InviteEvent) {
// Logic here
}
}
The idea is that, in my service I can autowire all my NotificationHandler
classes, call handle
on each one, and the internal logic will call handleInternal
if necessary.
@Service
@Transactional
class NotificationServiceImpl(
val notificationEventHandlers: List<NotificationEventHandler<*>>
) : NotificationService {
override fun onNotificationEvent(notificationEvent: NotificationEvent) {
notificationEventHandlers.forEach {
it.handle(notificationEvent)
}
}
I really do not like this implementation... when I see casting in my code, normally I'm doing something wrong (i.e. missing some design pattern or ignoring polymorphism powers). Moreover I'm invoking handle
on every handler instead of calling it only on supported ones.
Do you have some idea how to implement this without casting?
Thank you so much.
Francesco
Aucun commentaire:
Enregistrer un commentaire