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

发布于 2024-10-12 01:51:04 字数 538 浏览 3 评论 0原文

我们在工作中争论过在 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
}

就可读性而言,哪种方式是推荐的方式和可维护性?我更喜欢将代码保留在侦听器内,只有当代码太大时,才将其设为内部类。这里我假设代码在其他地方没有重复。

谢谢。

we had a debate at work about what is the best practice for using listeners in java: whether listener logic should stay in the anonymous class, or it should be in a separate method, for example:

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

or

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

private void buttonPressed() {
    // code here
}

which is the recommended way in terms of readability and maintainability? I prefer to keep the code inside the listener and only if gets too large, make it an inner class. Here I assume that the code is not duplicated anywhere else.

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

┼── 2024-10-19 01:51:04

我自己制定的规则是:

  1. 如果侦听器有超过 2 个方法,则创建一个命名类。
  2. 如果侦听器跨越 10 行以上,请创建一个命名类。

非常简单,易于遵循并生成或多或少可读的代码。但我不得不承认我从来没有想过你的例子表明了什么。

My self-imposed rule is:

  1. If the listener has more than 2 methods, create a named class.
  2. If the listener spans more than 10 lines, create a named class.

Pretty simple, easy to follow and produces more or less readable code. But then I have to admit that I never even thought of what your example shows.

楠木可依 2024-10-19 01:51:04

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

对于听众来说是否有更好的实践

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

This question is partially answered here:

Is there a better practice for listeners

I also do not like the Anonymous way for two reasons:
1) you cannot easily re-use the code so you may find that you have duplicate code after a while 2) I find it breaks up the reading of the code (others disagree... personal taste). I think everyone would agree that if you are doing more than 5-10 lines that an anonymous inner class is not a good idea (I would say more than 2 is too much).

夏天碎花小短裙 2024-10-19 01:51:04

我个人认为,“视情况而定”。如果侦听器仅添加到单个组件中,非常简单并且是 GUI 的组成部分,那么匿名内部类会很好地工作。如果监听器很复杂,会被添加到多个组件中,会有自己独立的状态,那么单独的独立类更好。介于两者之间的是私有内部类。 HTH。

编辑:我的错。我正在回答一个不同的问题——是否为侦听器使用单独的独立类。至于是否将匿名内部类代码保持内联还是在方法中,我同意其他发帖人的观点,这将取决于侦听器代码的大小和复杂性。

In my personal opinion, "it depends". If the listener is only to be added to a single component, is very simple and is an integral part of the GUI, then an anonymous inner class would work well. If the listener is complex, will be added to multiple components, will have its own separate state, then a separate stand alone class is better. In between is the private inner class. HTH.

Edit: My bad. I was answering a different question -- whether or not to use a separate stand-alone class for a listener. As for whether to keep anon inner class code inline vs. in a method, I agree with the other poster, it will depend on the size and complexity of the listener code.

梦途 2024-10-19 01:51:04

如果需要从匿名内部类之外的任何内容访问方法 buttonPressed(),那么请使用方法。否则只需将代码放在 actionPerformed() 中即可。

If the method buttonPressed() will ever need to be accessed from anything aside from the anonymous inner class, then use a method. Otherwise simply placing the code within actionPerformed().

西瓜 2024-10-19 01:51:04

根据我个人的经验,最好遵循 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 的逻辑实现为匿名类的一部分非常方便,因为它几乎没有什么可重用的。所有逻辑都封装到控制器中,因此操作实际上充当控制器调用的包装器,以用作按钮的模型。

In my personal experience it is best to follow the MVC pattern. This way there is a separate class representing a model, which creates all relevant actions, action listeners etc. It is preferable that actions are represented as final class fields, which are instantiated in the constructor.

For example:

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;
    }
}

The view is also represented by a separate class, which takes the model as its constructor parameter, where the actual button instantiation takes place. For example:

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

With this approach it is quite convenient to implement the logic of actionPerformed as part of the anonymous class since it has very little to be reused. All the logic is encapsulated into the controller, so the actions serve really as a wrapper around the controller call to be used as a model for a button.

烛影斜 2024-10-19 01:51:04

是的,这很大程度上取决于您想要做什么。我认为匿名内部类因为两个误区而受到了不好的批评。一是无法重用匿名代码。第二,内存泄漏。但这些问题可以通过简单的方法轻松解决。保存对实例的引用。为了共享代码,只需创建对匿名内部类的引用。

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

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

至于风格,我发现匿名侦听器非常方便,并且在某些情况下在处理 Swing 中的线程时更易于阅读,因为它将代码保留在一种方法中(invokeLater、executeInBackground 等)。当您将匿名侦听器委托给实例方法时,我认为它将代码分开,您无法在一个屏幕中读取侦听器之前发生的情况以及与侦听器关联的逻辑。他们往往会被分开,并且很难跟随。

需要注意的是,如果您使用 ActionMap,大多数与键盘监听相关的内存泄漏都会消失。不幸的是,诸如焦点侦听器或向中央系统注册的侦听器之类的事情仍然是一个问题。 (再次强调,WeakListener 在这里很棒)。而且您已经有一个位置来保存每个组件的操作,因此无需创建额外的实例变量来保存它。如果您需要跨两个组件(例如在菜单栏和控件中)重用,请创建一个单独的类。

Yes it depends highly on what you're trying to do. I think Anonymous inner classes have gotten a bad rap because of two myths. One is not being able to reuse anonymous code. And two, memory leaks. But these are easily fixed with a simple approach. Save a reference to the instance. For sharing code just create a reference to the anonymous inner class.

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

Now you can reuse that action across multiple components. For the later problem of memory leaks you can use that reference to unregister it, or the second and simpler option is WeakListeners. WeakListeners have the advantage of not needing to managed after their creation as much.

As for style I find Anonymous listeners to be quite handy, and in some cases easier to read when dealing with threading in Swing because it keeps your code in one method (invokeLater, executeInBackground, etc). When you anon listener delegates to an instance method I think it separates the code where you can't read what happened prior to the listener and the logic associated with the listener in one screen. They tend to get separated, and it's harder to follow.

Something to be aware of is if you use ActionMaps most of the memory leaks will go away associated with keyboard listening. Unfortunately things like focus listeners or listeners that are registered with central systems are still a problem. (Again WeakListeners are great here). And you already have a place to keep the action with every component so no need to create extra instance variables to hold it. If you need to reuse across two components (say in a menu bar and in a control) create a separate class.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文