Почему списки списков слушателей?
Почему списки слушателей (например, в Java, которые используют addXxxListener()
и removeXxxListener()
для регистрации и отмена регистрации слушателей), называются списками и обычно реализуются как Lists? Не лучше ли Set, так как в случае слушателей есть
- Независимо от того, в каком порядке они вызываются (хотя вполне могут быть такие потребности, но это особые случаи, обычные механизмы слушателя не дают таких гарантий), и
- Не нужно регистрировать одного и того же прослушивателя более одного раза (независимо от того, приведет ли это к вызову одного и того же прослушивателя 1 раз или N раз или будет ошибкой, это другой вопрос)
Это только вопрос традиции? В любом случае наборы - это какие-то списки под капотом. Существуют ли различия в производительности? Итерируется через List
быстрее или медленнее, чем итерация через Set
? Делает ли он более или менее память? Различия, безусловно, почти незначительны.
Ответы
Ответ 1
Одна из важных причин, по которой списки слушателей должны быть списками (вместо наборов), также объясняет, почему вы часто видите, что они повторяются в обратном порядке. Обычный сценарий включает слушателя, удаляющего себя в качестве слушателя, когда он уведомляется о некоторых изменениях. Если слушатели были сохранены в виде списка и итерации вперед (или сохранены в виде набора и итерированы в некотором неопределенном порядке), удаление себя в качестве слушателя вызовет исключение ConcurrentModificationException.
Итак, вместо этого слушатели хранятся в виде списка и уведомляются в обратном порядке. Затем, если прослушиватель удаляется из списка слушателей, когда он уведомлен, он не вызывает исключение ConcurrentModificationException или не меняет индексы других, но не уведомленных слушателей.
Ответ 2
Какой набор? Должны ли все слушатели использовать equals и hashCode, чтобы использовать хеш-набор или задан ли хэш-хэш? Является ли прецедент добавлением слушателя в список в два раза сложнее? Существует ли простой механизм для обеспечения безопасности набора для добавления или удаления прослушивателей во время вызовов их обработчиков?
Могут быть некоторые различия в производительности, но, безусловно, существует более сложный дизайн, и он заставляет множественное решение для добавления нескольких элементов в библиотеку, а не оставлять его в приложении.
Ответ 3
Вы совершенно правы. Слушатели должны быть добавлены к наборам. Как вы сказали, добавление слушателя более одного раза не имеет смысла. Кроме того, вы не будете полагаться на порядок слушателей, если будете использовать наборы. И это самое главное: НЕ ДОЛЖНО полагаться на него, если вы серьезно относитесь к разработке программного обеспечения и к каждому принципу, который мы выяснили, чтобы привести нас к лучшему дизайну: Изоляция, Независимость, Ответственность.
Каждый аспект, упомянутый здесь (многопоточность, производительность,...), должен подчиняться себе в первой мысли, но может быть нарушен, если у вас есть веские причины. И я имею в виду ОЧЕНЬ хорошие причины.
Кстати: Это плохая практика, позволяющая слушателю удалить себя. Добавление и удаление должно быть симметричным. Поэтому слушатель должен быть удален через объект, который его зарегистрировал. Если у вас много слушателей, вы скоро застрянете.