Как удалить зарегистрированных / добавленных слушателей? - PullRequest
0 голосов
/ 21 января 2011

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

interface SomeInterface {
  addListener( Listener) 
  removeListener( Listener );
}

Это, однако, отстой по нескольким причинам.

  • Возможно передатьa Слушатель, который еще не был удален для SomeInterface.removeListener ().
  • Также возможно вызвать SI.removeListener (), когда ни один слушатель не зарегистрирован.Нельзя вызывать команду remove до того, как даже выполнить добавление.
  • Это также означает, что для удаления на более позднем этапе необходимо сохранять дескриптор как Слушателя, так и ссылки SI.

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

Ответы [ 4 ]

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

Мое предложение заключается в том, чтобы метод AddListener возвращал объект типа ISubscriptionCanceller одним методом: CancelSubscription и, возможно, свойством SubscriptionActive.Этот объект будет содержать всю информацию, необходимую для отмены данной подписки, независимо от того, хранятся ли подписки в массиве, связанном списке или какой-либо новой структуре данных, которую еще предстоит изобрести.Естественно, было бы невозможно попытаться отменить подписку, которая еще не была запрошена, поскольку у нее не было бы необходимого ISubscriptionCanceller для этого.

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

Я не думаю, что ваши проблемы реальны.

Конечно, вы можете вернуть объект из addListener методом no-arg, чтобы удалить этого слушателя.Действительно, это упростило бы отмену регистрации полных слоев.Но я не думаю, что это необходимо.

1 голос
/ 21 января 2011

Это не так отстой, как ты думаешь, я полагаю. Есть много классов, которые используют этот шаблон. Если вы действительно хотите, вы можете заставить removeListener () возвращать true / false (true, если прослушиватель был действительно удален) или выдавать исключение (например, IllegalStateException) при попытке удалить незарегистрированного прослушивателя. Но вы действительно хотите это сделать? Что вы будете выполнять в случае исключения? В большинстве случаев это не имеет значения, поэтому я думаю, что сделать это просто. Ваш интерфейс в порядке.

Вы также можете добавить метод

Iterator listeners()

, который возвращает итератор. Таким образом, вы можете удалить слушателя во время итерации, используя Iterator.remove (). По крайней мере, в этом случае вы не сможете удалить незарегистрированного слушателя.

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

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

  1. Это невозможно в Java; Java не является динамическим языком (игнорируя отражение)
  2. Даже если бы это было возможно, как в javascript, как бы вы справились с тем фактом, что вы можете добавлять слушателей разных типов? Вы предлагаете метод удаления для каждого типа?

Обычно, если вы передаете прослушиватель, который не был зарегистрирован в какой-либо класс наблюдения, метод ничего не делает и, возможно, возвращает логическое значение, указывающее на успех или неудачу. Что хорошо, хорошо поняли. Я категорически отвергаю это утверждение: «Также возможно вызвать SI.removeListener (), когда ни один из прослушивателей не зарегистрирован. Никто не должен быть в состоянии вызвать remove, даже не делая добавления».

...