我有一个类EventGenerator
,它可以生成接口Event
的任何子类的对象。我想允许对象实现一种方法,该方法接收T
的特定子类Event
,当生成器发出该类型的新事件时将调用该子类。
由于将来可能会创建Event
的子类,因此我想尽可能地遵循开放式原则。
我正在考虑使用方法EventSubscriber<T extends Event>
的接口receiveEvent(T)
,但是如何在生成器对象中添加和存储订户?
编辑:假设我没有(也永远不会有)实现Event
接口的类的子类
答案 0 :(得分:0)
我假设您是在询问如何存储和访问订户。由于您不知道事件类,因此您需要在某个时候进行转换,但是可以在生成器内部进行处理。
一个简单的存储可以是Map<Class<? extends Event>, List<EventSubscriber<?>>
。
订户接口可以包含方法Class<T> getEventClass()
,该方法在注册订户时用作该映射的键。
触发事件时,您将使用事件的类来查找订户列表并获得一个List<EventSubscriber<?>>
。现在,您遍历这些对象并对其调用receiveEvent(event)
。由于存在通配符,您需要将每个元素都转换为原始类型EventSubscriber
,以使编译器使用桥接方法receiveEvent(Object)
。
请注意,因为您要确保使用相同的事件类来注册和查找订户,并且通配符隐藏在生成器中,所以这样做应该是安全的。我们一直在使用这样的东西:)
编辑:
以下是引发事件的示例:
void fireEvent( Event event ) {
List<EventSubscriber<?>> subscribers = subscriberMap.get( event.getClass() );
//This cast will cause warnings that you'll want to suppress
//via @SuppressWarnings ( { "rawtypes", "unchecked" } ) on the method level
subscribers.forEach(s -> ((EventSubscriber)s).receiveEvent( event ) );
}
内部,编译器将生成一个桥接方法receiveEvent( Object )
,它将在您将订阅方转换为原始类型时调用。如评论所述,这将生成警告,但是如果您确保查找将使用与实际参数类型相同的类,则可以安全地忽略这些类。