В моей программе есть около 50 событий, которые выбрасываются. У меня возникла проблема со стандартным способом получения событий.
Моей первой мыслью было использовать универсальный интерфейс и просто заставить слушателей реализовать это и добавить себя в очередь слушателей. К сожалению, это означало, что классы не могли иметь несколько слушателей из-за стирания типов и проблем множественного наследования . Поэтому я удалил код слушателя и начал заново.
Моя текущая (и оригинальная) установка состоит в том, чтобы иметь интерфейс, который прослушивает каждое событие. Например,
/**
* Listener for {@link myproject.hooks.events.FingerEvent}events
* @see myproject.hooks.events.Finger
*/
public interface FingerListener extends Listener {
/**
* Invoked when an {@link myproject.hooks.events.FingerEvent}occurs
* @param event The generated FingerEvent
*/
public void onFinger(FingerEvent event);
}
Все они расширяют интерфейс Listener
, который не содержит никаких методов, он просто так, что их все вместе можно назвать "Слушателями".
Проблема в том, что на событие приходится тонна кода. У вас есть событие и его получатели (к счастью, это было упрощено Project Lombok), затем интерфейс, который его получает, затем Javadoc на интерфейсе, чтобы, когда кто-то хочет получить информацию, он знает, где ее получить.
Другая проблема, с которой я сталкиваюсь, заключается в том, что у каждого слушателя есть свое имя метода, что приводит к очень интересному коду, пытающемуся выяснить, какой метод вызывать. Он хрупкий, медленный (использует отражение) и выглядит как дерьмо. Если вы мне не верите, тогда:
public static boolean callListener(Event event, Listener listener) {
//Get base name of event
String name = event.getClass().getSimpleName().split("Event")[0];
//Try and get the correct method if it exists
Method listenerMethod = null;
try {
listenerMethod = listener.getClass().getMethod("on"+name, event.getClass());
} catch (NoSuchMethodException ex) {
//Method doesn't exist, just don't call anything
return false;
} catch (SecurityException ex) {
throw new RuntimeException("Method on"+name+" is unaccessable", ex);
}
//Now that we have the method, attempt to execute it
try {
listenerMethod.invoke(listener, event);
} catch (Exception ex) {
throw new RuntimeException("Unexpected error when invoking method on"+name);
}
//Method executed sucessfully, return true
return true;
}
Это хотя и стандартный способ получения событий в java: есть интерфейс слушателя для каждого события, затем создать спагетти для вызова соответствующих методов, или я делаю это совершенно неправильно?