避免使用多态性(或设计模式)进行强制转换



我有以下类:

interface Event
interface NotificationEvent : Event
data class InviteEvent(val userId: Long, val inviteeId: Long) : NotificationEvent

Event表示泛型事件
NotificationEvent表示触发通知的事件
InviteEvent表示NotificationEvent的实现

我会编写一个对通知事件做出反应的代码,为每种类型的事件编写处理程序.
根据"打开-关闭"原则,我想避免编辑一些现有类来处理新类型的事件(即避免地狱开关情况(。 我想出的想法是创建以下类:

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
}
}

这个想法是,在我的服务中,我可以自动连接我所有的NotificationHandler类,在每个类上调用handle,如有必要,内部逻辑将调用handleInternal

@Service
@Transactional
class NotificationServiceImpl(
val notificationEventHandlers: List<NotificationEventHandler<*>>
) : NotificationService {
override fun onNotificationEvent(notificationEvent: NotificationEvent) {
notificationEventHandlers.forEach {
it.handle(notificationEvent)
}
}

我真的不喜欢这个实现...当我在代码中看到强制转换时,通常我做错了什么(即缺少一些设计模式或忽略多态能力(。 此外,我在每个处理程序上调用handle,而不是仅在支持的处理程序上调用它。

您知道如何在不强制转换的情况下实现这一点吗?

非常感谢.
Francesco

不知道这是否是你要找的,但它会避免未经检查的转换。

而不是只检查事件类型是否正确(notificationEvent is InviteEvent(,你可以尝试安全强制转换,将 issupport 更改为返回 T? 而不是布尔值,那么在实际实现中可以使用 event 作为?邀请事件或其他什么。

如果结果不为 null,则可以安全地使用它调用 handleInternal。

abstract class NotificationEventHandler<T : NotificationEvent> {
fun handle(notificationEvent: NotificationEvent){
castIfSupported(notificationEvent)?.let(this::handleInternal)
}
protected abstract fun handleInternal(notificationEvent: T)
protected abstract fun castIfSupported(event: NotificationEvent): T?
}
class InviteEventHandler : NotificationEventHandler<InviteEvent>() {
override fun handleInternal(notificationEvent: InviteEvent) {
println("this is an invite")
}
override fun castIfSupported(event: NotificationEvent): InviteEvent? {
return event as? InviteEvent
}
}

也许访客模式应该会有所帮助,你可以在这里或这里找到。它可用于处理同一层次结构中的对象。只需最少的修改(无强制转换(即可添加新对象。此模式的缺点是 Visitor 类(如下EventHandler(必须为所有可能的事件类型实现process()方法。这也是添加新事件类型时更改的位置。我不熟悉 Kotlin,以下只是伪代码:

class Event {
abstract process(EventHandler handler);
}
class NotificationEvent : Event {
process(EventHandler handler);
}
class InviteEvent : NotificationEvent {
process(EventHandler handler) {
handler.handle(this)
}
}
class ImportantEvent : NotificationEvent {
process(EventHandler handler) {
handler.handle(this)
}
}
class EventHandler {
process(InviteEvent event) {
...
}

process(ImportantEvent event) {
...
}
}
class CustomEventHandler : EventHandler {
process(ImportantEvent event) {
// customer processing
}
}
// run-time
EventHandler handler = new EventHandler();
EventHandler customHandler = new CustomEventHandler();
Event event = retrieveEvent(...)
Event importantEvent = retrieveImportantEvent(...)
event.process(handler);
importantEvent.process(handler); // default processing
importantEvent.process(customHandler); // custom processing

最新更新