Хорошая идея - использовать @annotations для обозначения методов слушателя, а не интерфейса с методами? - PullRequest
6 голосов
/ 29 января 2011

Во первых да - это субъективно.

Я заметил, что в последнее время несколько библиотек, похоже, используют методы прослушивания let пользовательского тега в некотором классе в качестве слушателей, использующих разные аннотации для записи различных событий. Infinispan и WELD приходят на ум в качестве примеров такого подхода.

Что я ненавижу в этом шаблоне

  • без типа безопасности
  • нужно прочитать документацию, чтобы узнать правильные сигнатуры типов для событий, а не просто реализовать.
  • для разработчика - еще один беспорядок, поскольку им требуется намного больше кода поддержки для обнаружения и проверки переданного класса слушателя, удержания метода и его отправки и т. Д.
  • Отражающая диспетчеризация замедляет события стрельбы. Конечно, можно создать реальный класс, используя ASM, но опять же, это намного больше работы по сравнению с простым простейшим listener.onEvent ...

ВОЗМОЖНЫЕ ПРИЧИНЫ

  • позволяет иметь мелкозернистых слушателей. Нет необходимости в пустых методах «ничего не делать», если у вас есть интерфейс Uber Listener. Аргумент счетчика состоит в том, чтобы не иметь интерфейс слушателя uber, а иметь множество интерфейсов с одним методом.

МНЕНИЯ

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

Ответы [ 2 ]

2 голосов
/ 29 января 2011

Может быть, интересный случай использования - ребята из спецификации Servlet 3.0 много боролись с этой проблемой. Самые ранние предложения покончили с такими интерфейсами, как, например, ServletContextListener и полагался исключительно на аннотации.

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

Среди прочего, по этой причине, предложение было жестко закрыто сообществом, и они сохранили интерфейсы. Теперь необходимую регистрацию в web.xml можно выполнить с помощью аннотаций, но определение методов слушателей по-прежнему осуществляется через интерфейсы.

Аннотации имеют свои преимущества. Мелкозернистые слушатели - это действительно одно. Вы не можете всегда противостоять этому с помощью мелкозернистых интерфейсов одного метода. Предположим, у меня есть (слушатель) интерфейс с 6 методами. Большинству людей нужен только 1 метод, поэтому вы решаете разбить его на 6 интерфейсов, каждый из которых имеет один метод. Теперь я счастливый парень, которому на самом деле нужны все 6 из них. В моем классе я должен теперь объявить, что я реализую 6 интерфейсов.

Я почти уверен, что многим это не понравится.

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

Кроме того, для аннотаций тривиально использовать несколько методов в одном классе. Вы не можете сделать это с интерфейсами. Существует только 1 метод, который реализует метод из интерфейса, не больше и не меньше.

Еще одно «преимущество» аннотаций состоит в том, что, поскольку они точно не определяют, к чему они применяются, можно поддерживать дополнительные сигнатуры методов позже. С интерфейсами вам придется добавить другой интерфейс. В моем примере с 6 интерфейсами, предположим, вы позже решите, что вам также необходимо поддерживать методы с 1 дополнительным параметром, вам потребуется 6 дополнительных интерфейсов. Это может сложить быстро.

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

0 голосов
/ 29 января 2011

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

, например

// called for each MyRecord
@Listener
public void onMyRecord(MyRecord r);

// when a batch of MyRecord is published, 
// call this method on the swing event thread.
@Listener(swing=true)
public void onMyRecords(MyRecord... rs)

// Listeners can have priority to determine the order of multiple listeners
// Called when any number of events are published with a priority of 5.
@Listener(priority=5)
public void onIMyEvent(IMyEvent ... events)
...