Anonymous class override vs passing an interface, for designing callbacks in Java

人盡茶涼 提交于 2019-12-11 18:23:39

问题


I'm aware of 3 different ways to do callback type functionality in Java, but I don't fully understand the pros/cons of each.

Java APIs are rich with methods similar in nature to this:

Button b = new Button();
b.setClickListener(<implements ClickListener>);

I'm using "button" as a generic example, not to refer to any specific API.

1.) One way to use it is to have your class implement the interface and pass it as the argument. To handle multiple "buttons" you'd have to use whatever information the caller provides to the callback to differentiate.

MyClass implements ClickListener
...
Button b = new Button();
b.setClickListener(this);
...
public void click(ButtonEvent e)
{
...

2.) Another way is to make an anonymous ClickListener on the spot and have its "click" method contain the code you want to execute. This has some added benefit because you can add new parameters to the callback by using local final variables.

for(int i=0 ; i<10 ; i++)
{
  final int finali = i;
  buttons[i] = new Button();
  buttons[i].setClickListener(new ClickListener()
  {
    public void click()
    {
      buttonClick(finali);
    }
  });
}

3.) The last way is possible if you're writing the class calling the callback. You could just anonymously override the callback method you want to catch. The most obvious downside is not being able to switch callbacks during the life of the object.

for(int i=0 ; i<10 ; i++)
{
  final int finali = i;
  buttons[i] = new Button()
  {
    public void click()
    {
      buttonClick(finali);
    }
  }
}

Option 3 seems to be the most "simple" in many ways. It doesn't require various interfaces to be made, and the callback function is always where the initialization is.

So my question is: What factors come into play when considering these design choices?


回答1:


Option 1 is often convenient, but becomes a problem if you want to listen to multiple objects, since you have to explicitly check which one has triggered the callback.

Option 2 avoids this problem, since each listener is separate; it is the most flexible of the three approaches.

Option 3 is a bad idea, since you are essentially taking over the Button rather than listening for events (i.e. this isn't really a callback at all); you may interfere with other code that is interested in the button, and the code will be harder to extend. Don't follow the Dark Side ;-).

And often you won't be writing the class that calls the callback...




回答2:


The first two are the same one. The only difference is who implements the listener interface. It uses the observable/observer design pattern.

The last one uses inheritance, and is much less flexible:

  • you can only set what must be done on a click when constructing the button
  • you can't alter this behavior afterwards
  • you can only register a single action to be made on a click
  • you can't remove the action on a click
  • you need to make your class non-final, and the click method overridable
  • you can't add the same listener to multiple buttons, leading to code duplication
  • ...

The first one is definitely a better option (and is the solution used by Swing, Android, JavaScript events, etc.). In general composition should be favored over inheritance. This case is a perfect example os this rule.



来源:https://stackoverflow.com/questions/13203966/anonymous-class-override-vs-passing-an-interface-for-designing-callbacks-in-jav

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!