简体   繁体   English

实施actionPerformed的最佳方式?

[英]Best way to implement actionPerformed?

In Java, we have two ways to implement actionPerformed:在Java中,我们有两种方式来实现actionPerformed:

  1. One actionPerformed method per class: use if-else to check event source;每个 class 的一种 actionPerformed 方法:使用 if-else 检查事件源;
  2. Use anonymous inner classes and implement the actionPerformed method in where that object is created;使用匿名内部类并在创建 object 的地方实现 actionPerformed 方法;

For option 1, it is easy to keep track of where the actionPerformed code is because there is only one method per class.对于选项 1,很容易跟踪 actionPerformed 代码的位置,因为每个 class 只有一个方法。 We can easy locate that method and then look inside to find the code we are looking for.我们可以轻松找到该方法,然后查看内部以找到我们正在寻找的代码。 However, there may be too many if-else clauses if we have many action listeners.但是,如果我们有很多动作监听器,可能会有太多的 if-else 子句。

For option 2, it is not easy to find where the actionPerformed code is because it is scattered all over the class.对于选项 2,不容易找到 actionPerformed 代码的位置,因为它分散在 class 各处。 If you have many action listeners, it will be more difficult to keep track of the actionPerformed instances.如果您有许多动作侦听器,则跟踪 actionPerformed 实例将更加困难。

I personally prefer option 1 because it is much easier to maintain the code, even the performance may be less efficient than option 2.我个人更喜欢选项 1,因为它更容易维护代码,甚至性能可能不如选项 2。

What are the pros and cons of each method?每种方法的优缺点是什么? What else should be taken into consideration when choosing how to implement actionPerformed?在选择如何实现 actionPerformed 时还应该考虑什么? Which way do you prefer?你更喜欢哪种方式?

EDIT:编辑:

so there is a 3rd option based on the suggestion from A. Lee below.因此,根据下面 A. Lee 的建议,有第三个选项。 it is a combination of the option 1 and option 2: use anonymous inner classes but put them altogether in ONE place within a class.它是选项 1 和选项 2 的组合:使用匿名内部类,但将它们完全放在 class 中的一个位置。 I think it is a good idea.我认为这是个好主意。

I think the long if-else chain in an actionPerformed method is ugly for several reasons - you make unnecessary checks every time to determine which is the appropriate receiver code for the ActionEvent and as the code grows it becomes increasingly unmaintainable.我认为 actionPerformed 方法中长长的 if-else 链很难看,原因有几个 - 您每次都进行不必要的检查以确定哪个是ActionEvent的合适接收器代码,并且随着代码的增长,它变得越来越难以维护。

If you want to have all your action handlers in one place, have an initializeActionListeners method that binds your ActionListeners to your controls.如果您希望将所有操作处理程序放在一个位置,请使用一个将您的 ActionListeners 绑定到控件的initializeActionListeners方法。 Or bind them where you initialize them so the event handler is closer to your widget/control itself, eg,或者将它们绑定在您初始化它们的位置,以便事件处理程序更接近您的小部件/控件本身,例如,

// not thread-safe
private JLabel getSomeLabel() {
    if (someLabel == null) {
        someLabel = new JLabel("Some label, huh");
        someLabel.addActionListener(...)
    }
    return someLabel;
}

Wrong alternatives: the question is not anonymous classes vs. a long big if-else construct (you can easily have the latter in the former).错误的选择:问题不是匿名类与一个长的大 if-else 构造(你可以很容易地在前者中使用后者)。 The question is whether to have a semantically strong class (anonymous or not) which does exactly one job, is the only one that does it ans does it completely.问题是是否有一个语义强大的 class (匿名与否),它只完成一项工作,是唯一一个完成它并且完全完成它的工作。 After all, we are in OO-land;-)毕竟,我们在 OO 领域;-)

So: strict no-no-ever to any if-then-else structs.所以:严格禁止任何 if-then-else 结构。

I use a third option, I wrote my own Manager that bind methods to JButtons directly through annotations.我使用第三个选项,我编写了自己的 Manager,它通过注释直接将方法绑定到 JButtons。

I provide it as a OpenSource project, you can check it on https://github.com/MarkyVasconcelos/Towel/wiki/ActionManager我将它作为一个开源项目提供,您可以在https://github.com/MarkyVasconcelos/Towel/wiki/ActionManager上查看它

The pros is that you don't need implement any ActionListener, and don't neeed Anonymous Inner Classes.优点是您不需要实现任何 ActionListener,也不需要匿名内部类。

All Actions are in the methods of your class.所有操作都在您的 class 的方法中。

In most cases, there isn't much difference, to suggest one over the other.在大多数情况下,没有太大区别,建议一个优于另一个。

I would say: If the cases are similar, put them together, but only to call the appropriate method from there:我会说:如果情况相似,请将它们放在一起,但只是从那里调用适当的方法:

    public void actionPerformed (ActionEvent e)
    {
            String cmd = e.getActionCommand ();
            if (cmd.equals (cmdNextPage))        nextPage ();
            else if (cmd.equals (cmdLastPage))   lastPage ();
            else if (cmd.equals (cmdOk))         ok ();
            // ... and so on

This way, you can call the methods easily, independent from an event, maybe from a testing framework, or for some undo/replay.这样,您可以轻松地调用方法,独立于事件,可能来自测试框架,或者用于某些撤消/重放。 The common pattern is obviously visible.共同的模式是显而易见的。

In very rare cases you might be interested in unregistering single events, and sources independently.在极少数情况下,您可能对注销单个事件和独立来源感兴趣。 Then, a single listener per ActionEvent seems better suited.然后,每个 ActionEvent 的单个侦听器似乎更适合。

From a pure OOP perspective, I think a single listener per Button (for example) is more straight forward, and from an imature optimization wish, I don't feel comfortable with 20 or 40 ActionListeners, but in my rational moments, I don't believe 40 ActionListeners have a measurable impact.从纯粹的 OOP 的角度来看,我认为每个按钮(例如)单个侦听器更直接,并且从不成熟的优化愿望来看,我对 20 或 40 个 ActionListener 感到不舒服,但在我理性的时候,我不相信 40 个 ActionListener 会产生可衡量的影响。 But they clutter up your Filesystem, your IDE-Browser, so I guess there is a rational reason in the end, to keep the number of Listeners low.但是它们会弄乱你的文件系统,你的 IDE 浏览器,所以我想最终有一个合理的理由,将监听器的数量保持在低水平。

A common Listener is easy to use in a button factory:一个普通的监听器在按钮工厂中很容易使用:

    private void addButton (JPanel jp, String cmd, String ttt)
    {
            JButton jb = new JButton (cmd);
            jb.setToolTipText (ttt);
            jp.add (jb);
            jb.addActionListener (this);
            buttonlist.add (jb);
    }

    /**   @return a Panel with Action-Buttons.     */
    private JPanel createControlPanel ()
    {
            JPanel m = new JPanel ();
            m.setLayout (new BoxLayout (m, BoxLayout.Y_AXIS));

            JPanel jpc = new JPanel ();
            jpc.setLayout (new FlowLayout ());
            buttonlist = new ArrayList <JButton> ();

            addButton (jpc, cmdLastPage, "last page");
            addButton (jpc, cmdNextPage, "next page");
            addButton (jpc, cmdOk, "save");
            addButton (jpc, cmdEsc, "exit");

It is very easy and clear, where to add a new button and how.在哪里添加新按钮以及如何添加非常简单明了。 I find it very maintainable.我觉得它非常易于维护。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM