Интерфейс слушателя при написании пользовательских событий

Я пытаюсь написать пользовательское событие. Я читал, что у меня должно быть 3 вещи: 1. Класс компонентов, 2. Класс событий и 3. Интерфейс прослушивателя.

Моя проблема в том, что мне нужно сделать набор слушателей в одном из классов следующим образом:

public class MyEvent{
     private Set<EventListener> = new HashSet<>();
        public synchronized void addListener(EventListener listener){
        listeners.add(listener);
     }

      //and the rest of the code for firing event .. 

}

а вот интерфейс:

 public interface EventListener {
      void hungry(MyEvent event);
 }

Я не могу понять, что значит иметь набор интерфейсов?


person Shaghayegh Tavakoli    schedule 15.07.2018    source источник


Ответы (2)


Здесь каждый элемент Set является слушателем события:

 private Set<EventListener> = new HashSet<>();

В вашем дизайне кажется, что несколько подписчиков могут подписаться на уведомление об одном и том же событии.
Например, предположим, что у вас есть событие: "приложение запущено". Возможно, несколько объектов хотят знать об этом событии уведомления.

Обратите внимание, что событие обычно не хранит слушателей (или наблюдателей). Роль компонента (или наблюдаемого) заключается в их хранении. Вы также должны предоставить способ уведомления слушателей. Например :

public class MyComponent{
     private Set<EventListener> listeners = new HashSet<>();

     public synchronized void addListener(EventListener listener){
        listeners.add(listener);
     }

     public void notify(MyEvent myEvent){
        listeners.stream().forEach(e->e.hungry(myEvent));
     }
}

И вы можете установить отношения между объектами таким образом:

MyComponent component = new MyComponent();
EventListener fooListener = new EventListenerImpl(...);
EventListener barListener = new EventListenerImpl(...);
component.addListener(fooListener);
component.addListener(barListener);
// trigger the event
component.notify(new HugryEvent());
person davidxxx    schedule 15.07.2018
comment
Спасибо. У меня есть вопрос о наблюдателе и наблюдаемом, о котором вы упомянули. не могли бы вы объяснить немного больше, как это работает? Я прочитал об этом здесь и не могу понять разницу между шаблоном наблюдателя и тем, что Я делаю здесь с классом события, интерфейсом слушателя и классом компонента? - person Shaghayegh Tavakoli; 15.07.2018
comment
Observer/Observable и Listeners — очень близкие шаблоны. Для простоты вы должны рассматривать это как два способа реализации связи без прямой связи для объекта, который будет уведомлен, когда другой объект изменит свое состояние. Оба шаблона работают с событиями и полагаются на несвязанную связь, а низкая связанность обеспечивается благодаря использованию интерфейса (наблюдатель или слушатель). - person davidxxx; 15.07.2018

Набор интерфейсов — это, по сути, набор интерфейсов или, в просторечии, «связка» интерфейсов.

Использование HashSets предотвращает случайное добавление одного и того же слушателя:

myEvent.addListener(this);
// some lines of code later...
myEvent.addListener(this);

Тот же слушатель будет иметь тот же хэш-код, и HashSet.add не добавит элемент в набор в такой ситуации. Обратите внимание, что интерфейсы также имеют методы hashCode, потому что они объявлены в Object.

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

Одна ситуация, когда это нежелательно, о которой я могу думать:

Вы пишете игру, а прослушиватель событий обрабатывает нажатие кнопки «купить». Если прослушиватель вызывается дважды, когда пользователь щелкнул его только один раз, игрок может неожиданно потерять деньги.

person Sweeper    schedule 15.07.2018