【问题标题】:Anonymous class override vs passing an interface, for designing callbacks in Java匿名类覆盖与传递接口,用于在 Java 中设计回调
【发布时间】:2012-11-02 22:37:49
【问题描述】:

我知道在 Java 中实现回调类型功能的 3 种不同方法,但我并不完全了解每种方法的优缺点。

Java API 有很多本质上与此类似的方法:

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

我使用“按钮”作为一个通用示例,而不是指任何特定的 API。

1.) 使用它的一种方法是让您的类实现接口并将其作为参数传递。要处理多个“按钮”,您必须使用调用者提供给回调的任何信息来区分。

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

2.) 另一种方法是在现场创建一个匿名 ClickListener,并让其“click”方法包含您要执行的代码。这有一些额外的好处,因为您可以使用本地最终变量向回调添加新参数。

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.) 如果您正在编写调用回调的类,则最后一种方法是可能的。您可以匿名覆盖您想要捕获的回调方法。最明显的缺点是无法在对象生命周期内切换回调。

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

选项 3 在许多方面似乎是最“简单”的。不需要制作各种接口,回调函数总是在初始化的地方。

所以我的问题是:在考虑这些设计选择时,哪些因素会起作用?

【问题讨论】:

  • 你忘记了另一个重要的“选项”,一个独立的处理程序类,如果你愿意的话,还有一个 control 类。

标签: java interface callback anonymous


【解决方案1】:

选项 1 通常很方便,但如果您想监听多个对象,就会出现问题,因为您必须明确检查哪个触发了回调。

选项 2 避免了这个问题,因为每个监听器都是独立的;它是三种方法中最灵活的。

选项 3 是个坏主意,因为您实际上是在接管 Button 而不是监听事件(即,这根本不是真正的回调);您可能会干扰对按钮感兴趣的其他代码,并且代码将难以扩展。不要跟随黑暗面;-)。

通常你不会编写调用回调的类...

【讨论】:

  • 我的意思是说我正在编写案例 3 中的“按钮”类。所以我将“click()”方法设置为专门用于覆盖和捕获事件的虚拟方法。跨度>
  • 好的,已经编辑了我的答案。通常仍然值得为您自己的类实现侦听器(选项 1 和 2),尽管这当然是一种设计折衷。
  • 选项 4 是避免回调/侦听器迷宫并使用小型简单总线(例如 Guava 中的 EventBus)。
【解决方案2】:

前两个是同一个。唯一的区别是谁实现了监听器接口。它使用 observable/observer 设计模式。

最后一个使用继承,灵活性差很多:

  • 在构建按钮时,您只能设置单击时必须执行的操作
  • 之后您无法更改此行为
  • 您只能注册一个点击操作
  • 您无法删除点击操作
  • 您需要使您的类成为非最终类,并且 click 方法可被覆盖
  • 不能将同一个监听器添加到多个按钮,导致代码重复
  • ...

第一个绝对是更好的选择(并且是 Swing、Android、JavaScript 事件等使用的解决方案)。一般来说,组合应该优先于继承。这个案例就是这个规则的完美范例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多