Упрощенная обработка пользовательских событий в Java

В Java каждый раз, когда я хочу создать новое пользовательское событие, я обычно делаю это, добавляя 3 метода, а именно:

addDogEventListener(EventListener listener); 
removeDogEventListener(EventListener listener);
dispatchDogEventListener(DogEvent event);

Теперь, если я хочу отправить другое событие, скажем, CatEvent, мне придется снова создать все эти 3 метода:

addCatEventListener(EventListener listener); 
removeCatEventListener(EventListener listener);
dispatchCatEventListener(CatEvent event);

Тогда, если я хочу управлять только одним событием CatEvent, скажем, «Мяу», мне нужно снова скопировать и вставить все эти 3 метода?! Например, addCatMeowEventListener();... и т. д.?

И обычно мне нужно отправлять более одного типа событий. Было бы очень неаккуратно, если бы весь класс был заполнен таким количеством методов для передачи и обработки событий. Мало того, эти функции имеют очень похожий код, например циклический просмотр EventListenerList, добавление события в список и т. д.

Это то, как я должен выполнять диспетчеризацию событий в Java?

Есть ли способ, как я могу сделать это так:

mainApp.addEventListener(CatEvent.MEOW, new EventHandler() { meowHandler(Event e) { });
mainApp.addEventListener(CatEvent.EAT, new EventHandler() { eatHandler(Event e) { });
myCat.addEventListener(DogEvent.BARK, new EventHandler() { barkHandler(Event e) { myCat.run() });

Таким образом, я могу просто обрабатывать различные типы CatEvent в разных классах и функциях eventHandler, и мне не нужно создавать разные методы прослушивания событий для разных событий?

Может быть, я что-то упустил в обработке событий Java, но есть ли более аккуратный способ, которым мне не нужно копировать и вставлять 3 метода, а также создавать так много разных типов объектов событий для каждого типа методов, которые я хочу отправить?

Спасибо!


person Carven    schedule 28.05.2011    source источник


Ответы (2)


Затем, если я хочу управлять только одним событием CatEvent, скажем, Meow (и EAT)

«Действие» события (MEOW или EAT) должно быть данными, определенными в CatEvent. Затем ваш код прослушивания событий проверит тип действия и выполнит соответствующую обработку.

Возможно, взгляните на TableModelEvent, чтобы увидеть, как это делается. Он обрабатывает события «вставить», «удалить» и «обновить», используя одно и то же событие.

Также вы, вероятно, могли бы смоделировать общий прослушиватель событий на основе PropertyChangeListener. PropertyChangeListener используется для обработки событий при изменении различных свойств компонента Swing. Например, когда вы вызываете setForeground(), setBackground(), setFont(), setText() или setIcon. Слушатель PropertyChangeListener использует метод getName(), чтобы определить, какое свойство было изменено. Таким образом, для вышеуказанных методов имена будут «передний план», «фон», «шрифт», «текст», «значок». См. Как использовать прослушиватели изменений свойств, чтобы узнать, как это может работать.

В вашем случае имена будут «кошка» и «собака». Этот подход будет работать только в том случае, если создаваемое вами GeneralEvent может содержать информацию, относящуюся к каждому из ваших событий (например, "мяу" и "лай").

person camickr    schedule 28.05.2011

Стратегия обработки событий, которую я использую, заключается в публикации по типу, который может вам подойти.

У меня есть брокер, который может проверять слушателя на наличие аннотации, которая помечает метод как прослушивание событий. Используя этот подход, вам нужно добавлять методы только тогда, когда вы хотите обработать определенный класс событий.

interface Subscriber { // marker interface for OSGi
}

@interface SubscriberCallback { // marker annotation
}

class Broker {
    // uses reflections to find methods marked with @SubscriberCallback
    public void addSubscriber(Subscriber subscriber); 
    public void removeSubscriber(Subscriber subscriber);
    public <T> void publish(T... events);
}

class MyListener implements Subscriber {

@SubscriberCallback
public void onDogEvent(DogEvent... dogEvents) {
    // called for one or more dog events
}

@SubscriberCallback
public void onCatEvent(CatEvent catEvent) {
    // called for each CatEvent including subsclass of CatEvent.
}
}
person Peter Lawrey    schedule 28.05.2011
comment
Но как метод публикации, запускающий событие, узнает, какое событие запускать? Кстати, я не использую OSGi. Так эти еще будут работать? Я раньше не использовал OSGi, а также новичок в Java, так как обычно использую другие языки. Извините, если я кажусь запутанным. - person Carven; 28.05.2011
comment
Каркас iPOJO в OSGi автоматически регистрирует/отменяет регистрацию всех слушателей. Вам придется добавлять/удалять их самостоятельно, вызывая broker.addSubscriber(subscriber) в коде. Существует только один метод публикации, так как он проверяет тип во время выполнения. - person Peter Lawrey; 28.05.2011