Шаблон подписки на события в Java - PullRequest
0 голосов
/ 07 июня 2019

У меня есть этот класс EventGenerator, который может генерировать объекты любого подкласса интерфейса Event. Я хотел бы позволить объектам реализовывать метод, который получает определенный подкласс T из Event, который будет вызываться, когда генератор генерирует новое событие этого типа.

Я бы хотел как можно больше следовать принципу Открыто-Закрыто, поскольку в будущем могут быть созданы подклассы Event. Я думал об интерфейсе EventSubscriber<T extends Event> с методом receiveEvent(T), но как мне добавить и сохранить подписчика в объекте генератора?

РЕДАКТИРОВАТЬ: Предположим, что у меня нет (и никогда не будет) подклассов классов, которые реализуют Event интерфейс

1 Ответ

0 голосов
/ 07 июня 2019

Я полагаю, вы спрашиваете о том, как хранить и получать доступ к подписчикам.Так как вы не знаете классы событий, которые вам нужно будет привести в какой-то момент, но это может быть обработано внутри генератора.

Простое хранилище может быть 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 ), который будет вызываться для необработанного типа, к которому вы привели подписчика.Как говорится в комментарии, это будет генерировать предупреждения, но если вы убедитесь, что поиск будет использовать тот же класс, что и фактический тип параметра, то их можно безопасно игнорировать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...