Java中的事件订阅模式

时间:2019-06-07 15:23:35

标签: java design-patterns

我有一个类EventGenerator,它可以生成接口Event的任何子类的对象。我想允许对象实现一种方法,该方法接收T的特定子类Event,当生成器发出该类型的新事件时将调用该子类。

由于将来可能会创建Event的子类,因此我想尽可能地遵循开放式原则。 我正在考虑使用方法EventSubscriber<T extends Event>的接口receiveEvent(T),但是如何在生成器对象中添加和存储订户?

编辑:假设我没有(也永远不会有)实现Event接口的类的子类

1 个答案:

答案 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 ),它将在您将订阅方转换为原始类型时调用。如评论所述,这将生成警告,但是如果您确保查找将使用与实际参数类型相同的类,则可以安全地忽略这些类。