开发者

How to remove registered/added Listeners?

开发者 https://www.devze.com 2023-02-06 01:50 出处:网络
Typically interfaces that let you add listeners also include a remove method something like the following.

Typically interfaces that let you add listeners also include a remove method something like the following.

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

This however suck for several reasons.

  • It is possible to pass a Listener that has not yet been removed to SomeInterface.removeListener().
  • 开发者_StackOverflow社区
  • It is also possible to call SI.removeListener() when no Listeners haven registered. One should not be able to call remove before even doing an add.
  • It also means one has to keep a handle of both the Listener and the SI reference in order to remove at some later stage.

I have a proposal which I believe works solves the those three problems, however I want to hear from others to learn from their ideas and proposals which might be more elegant than my own solution.


My proposal would be to have the AddListener method return an object of type ISubscriptionCanceller with one method: CancelSubscription and possibly a SubscriptionActive property. This object would contain all information necessary to cancel a given subscription, whether subscriptions are stored in an array, linked list, or some new data structure yet to be invented. It would naturally be impossible to attempt to cancel a subscription that had not yet been requested, since one would not have the necessary ISubscriptionCanceller to do so.


I don't think your problems are real.

Sure you could return an object from addListener with a no-arg method to remove that listener. Indeed that would simplify deregistration of complete layers. But I don't think it's necessary.


It is not so suck as you think, I believe. There are many classes that use this pattern. If you really want you can make removeListener() to return true/false (true if the listener has been really removed) or throw exception (e.g. IllegalStateException) when attempting to remove unregistered listener. But do you really want to do this? What will you perform in case of exception? In most cases it does not matter, so I think that make is simple. Your interface is OK.

You can also add method

Iterator listeners()

that returns iterator. So, you can remove listener while iterating using Iterator.remove(). At least in this case you will not be able to remove unregistered listener.


I think a lot of your underlying assumptions are wrong. Lets consider the alternative in Java, that removeListener is not a method on the class until a listener has been registered.

  1. This isn't possible in Java; Java is not a dynamic language (ignoring reflection)
  2. Even if it was possible, as it is in javascript, how would you deal with the fact that you can add listeners of different types? Do you propose a remove method for each type?

Typically if you pass in a listener that has not been registered to some sort of observing class, the method will do nothing and perhaps return a boolean indicating success or failure. Which is fine, well understood. I utterly reject this statement: "It is also possible to call SI.removeListener() when no Listeners haven registered. One should not be able to call remove before even doing an add."

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号