2009-08-24 2 views
3

Должно ли addListener проверить метод для повторной регистрации при вызове? Если да, то что должно произойти при обнаружении дубликата?При регистрации на события Java обычно допускаются дубликаты слушателей?

final public class exampleCanFire { 
    public void addFooListener(FooListener listener) { 
     // Before adding listener to private list of listeners, should I check for duplicates? 
    } 
} 
+2

Хотя я Не знаю ответа, с точки зрения дизайна библиотеки, конечно, единственная согласованная вещь для библиотеки - зарегистрировать всех слушателей (включая дубликаты)? В противном случае, если две разные подсистемы случайно зарегистрировали один и тот же прослушиватель, тогда первый, кто отменит регистрацию, испортит другую подсистему - правильно? –

+1

Было бы бесполезно, так же как получать каждое событие дважды, потому что кто-то еще повторно регистрирует вашего слушателя. – Zed

+0

@ Zed: Да, но я бы сказал, что это вина человека, который небрежно объединил две подсистемы. Должна быть ответственность человека, который объединяет несвязанные «равные» подсистемы, чтобы знать, как они будут взаимодействовать, поскольку альтернатива для каждой подсистемы заключается в том, чтобы знать, как взаимодействовать с любой другой несвязанной «одноранговой» подсистемой, которая в настоящее время существует или может существовать в будущее, и это нежизнеспособно. –

ответ

4

Я предпочитаю хранить их в List и не проверять на наличие дубликатов. Некоторые преимущества такого подхода:

  • Слушатели уведомляются в детерминированном порядке и могут помечать события как «потребляемые», которые не распространяются на последующих слушателей.
  • Можно использовать CopyOnWriteArrayList реализации, что позволяет слушателю, чтобы удалить себя во время уведомления обратного вызова без ConcurrentModificationException будучи брошенной (это очень важно и является классическим Гоча при написании событий ориентированного кода).
+1

+1 для 'CopyOnWriteArrayList'. – Bombe

+0

Первая точка полностью действительна, но во 2-й точке также имеется экземпляр CopyOnWriteArraySet, который потенциально может быть использован. Но да, используя Списки, вероятно, будет лучшим вариантом, убедившись, что один не регистрирует дубликатов слушателей, должен быть до клиента –

3

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

Если вы действительно хотели что-то сделать, я бы предложил бросить IllegalArgumentException с сообщением о том, что вы не можете зарегистрировать один и тот же прослушиватель дважды.

0

Хранить их в наборе, и распространять все, что ответ Сета является:

Set<FooListener> listeners = new HashSet<FooListener>(); 

public boolean addFooListener(FooListener listener) { 
    return listeners.add(listener); 
} 
0

Если найдено списков, которые будут намного медленнее, чем при использовании методов, рекомендованных JAVA. Я предполагаю, что методы JAVA имеют более непосредственное взаимодействие с памятью или что-то в этом роде. Независимо от того, я согласен с j_random_hacker в том, что вы должны знать, что вызывает то, что когда и впоследствии рискует дублировать слушателей, испортить друг друга в результате действий, но именно поэтому мы тестируем наши программы, не так ли ;-)

Смежные вопросы