Java:我应该在哪里放置匿名监听器逻辑代码?

时间:2011-01-15 19:15:05

标签: java swing listener anonymous-class

我们在工作中讨论了在java中使用监听器的最佳实践:监听器逻辑是应该保留在匿名类中,还是应该在单独的方法中,例如:

button.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        // code here
    }
});

button.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        buttonPressed();
    }
});

private void buttonPressed() {
    // code here
}

这是可读性和可维护性方面的推荐方法?我更喜欢将代码保留在侦听器中,并且只有当它变得太大时才使其成为内部类。在这里,我假设代码在其他任何地方都没有重复。

谢谢。

6 个答案:

答案 0 :(得分:4)

我自我强加的规则是:

  1. 如果侦听器有两个以上的方法,请创建一个命名类。
  2. 如果侦听器跨越10行,则创建一个命名类。
  3. 非常简单,易于理解并生成或多或少的可读代码。但后来我不得不承认我从未想过你的例子所展示的内容。

答案 1 :(得分:2)

这个问题在这里得到了部分答案:

Is there a better practice for listeners

  

我也不喜欢匿名方式有两个原因:
  1)你不能轻易地重复使用代码,所以你可能会发现你有一段时间后重复代码2)我发现它打破了代码的阅读(其他人不同意......个人品味)。我想每个人都会同意,如果你做的超过5-10行,那么一个匿名的内部课程不是一个好主意(我会说超过2个是太多了)。

答案 2 :(得分:1)

在我个人看来,“这取决于”。如果只将侦听器添加到单个组件中,非常简单并且是GUI的组成部分,那么匿名内部类就可以正常工作。如果监听器很复杂,会被添加到多个组件中,会有自己独立的状态,那么单独一个独立的类就更好了。中间是私人内部阶级。 HTH。

编辑:我的坏。我正在回答一个不同的问题 - 是否为听众使用单独的独立课程。至于是否将内部内部代码保持在内联类代码与方法中,我同意另一张海报,它将取决于侦听器代码的大小和复杂性。

答案 3 :(得分:1)

如果除了匿名内部类之外的任何东西都需要访问方法buttonPressed(),那么使用方法。否则只需将代码放在actionPerformed()

答案 4 :(得分:1)

根据我的个人经验,最好遵循MVC模式。这种方式有一个单独的类代表一个模型,它创建所有相关的动作,动作监听器等。最好将动作表示为最终的类字段,它们在构造函数中实例化。

例如:

public class Model {
    private final Action buttonAction;
    ...

    public Model(final IController controller) {
       buttonAction = createButtonAction(controller);
       ...
    }

    private Action createButtonAction(final IController controller) {
        Action action = new Action("Action") {
            public void actionPerformed(final ActionEvent e) {
                // do the required action with long running ones on a separate Thread
                controller.run();
            }
        };
        action.set...// other initialisation such as icon etc
        ...
        return action;
    }
    ...

    public Action getButtonAction() {
        return buttonAction;
    }
}

视图也由一个单独的类表示,该类将模型作为其构造函数参数,在该实例中进行实际的按钮实例化。例如:

public class View extends JPanel {
    public View(final Model model) {
       ...
       JButton button = new JButton(model.getButtonAction();
       ...
    }
}

使用这种方法,将actionPerformed的逻辑作为匿名类的一部分实现是非常方便的,因为它几乎没有被重用。所有逻辑都封装在控制器中,因此这些操作实际上是作为控制器调用的包装器,用作按钮的模型。

答案 5 :(得分:0)

是的,这在很大程度上取决于你要做的事情。我认为,由于两个神话,匿名内部阶级已经得到了糟糕的说唱。一个是无法重用匿名代码。二,内存泄漏。但这些很容易通过简单的方法解决。保存对实例的引用。对于共享代码,只需创建对匿名内部类的引用。

Action action = new AbstractAction("Open") {...};
JButton button = new JButton( action );
JMenuItem menuItem = new JMenuItem( action );
panel.getActionMap().put("openFile", action );

现在,您可以跨多个组件重用该操作。对于后来的内存泄漏问题,您可以使用该引用取消注册它,或者第二个更简单的选项是WeakListeners。 WeakListeners的优点是不需要在创建之后进行管理。

至于样式,我发现Anonymous监听器非常方便,在某些情况下在Swing中处理线程时更容易阅读,因为它将代码保存在一个方法中(invokeLater,executeInBackground等)。当你的匿名监听器委托给一个实例方法时,我认为它将代码分开,你无法在一个屏幕中读取监听器之前发生的事情和与监听器相关的逻辑。他们往往分开,而且更难以遵循。

需要注意的是,如果使用ActionMaps,大多数内存泄漏都会因键盘监听而消失。不幸的是,像中央系统注册的焦点听众或听众这样的东西仍然是个问题。 (再次WeakListeners在这里很棒)。并且您已经有了一个位置来保持每个组件的操作,因此无需创建额外的实例变量来保存它。如果需要重用两个组件(比如在菜单栏和控件中),请创建一个单独的类。