【问题标题】:Best way to implement actionPerformed?实现actionPerformed的最佳方式?
【发布时间】:2011-05-02 16:56:37
【问题描述】:

在Java中,我们有两种方式来实现actionPerformed:

  1. 每个类一个 actionPerformed 方法:使用 if-else 检查事件源;
  2. 使用匿名内部类并在创建该对象的位置实现 actionPerformed 方法;

对于选项 1,很容易跟踪 actionPerformed 代码的位置,因为每个类只有一个方法。我们可以轻松找到该方法,然后查看内部以找到我们正在寻找的代码。但是,如果我们有很多动作监听器,可能会有太多的 if-else 子句。

对于选项 2,不容易找到 actionPerformed 代码的位置,因为它分散在整个类中。如果您有许多动作侦听器,则跟踪 actionPerformed 实例将更加困难。

我个人更喜欢选项1,因为它更容易维护代码,甚至性能可能不如选项2。

每种方法的优缺点是什么?在选择如何实现 actionPerformed 时还应该考虑什么?你更喜欢哪种方式?

编辑:

所以根据下面 A. Lee 的建议,有第三个选项。 它是选项 1 和选项 2 的组合:使用匿名内部类,但将它们完全放在类中的一个位置。 我认为这是个好主意。

【问题讨论】:

  • 可能类似的话题(今天)stackoverflow.com/questions/5856083/…
  • 如果你想被困在程序编码器中,请选择 1 ;-) 对于 OO 来说,这是不可能的
  • 为什么选项 2 是 OO 而选项 1 不是?因为选项 2 将所有代码放在一起并且可以轻松复制到另一个地方?还是因为我们将动作与对象分开了?
  • 仔细阅读 - 我没有说 2 是 OO ;-)

标签: java


【解决方案1】:

我认为 actionPerformed 方法中长长的 if-else 链之所以丑陋,有几个原因 - 您每次都进行不必要的检查以确定哪个是适合 ActionEvent 的接收器代码,并且随着代码的增长,它变得越来越难以维护。

如果您想将所有操作处理程序放在一个位置,请使用initializeActionListeners 方法将您的 ActionListeners 绑定到您的控件。或者将它们绑定到您初始化它们的位置,以便事件处理程序更接近您的小部件/控件本身,例如,

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

【讨论】:

  • initializeActionListeners 会像这样:
  • initializeActionListeners 会这样吗?私有无效初始化ActionListener() { someLabel.addActionListener(new ActionListener(){ 公共无效actionPerformed(ActionEvent e){...}}); someBtn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e){}}); ... }
  • 您是否担心 20 或 40 次不必要的检查对性能的影响?我不认为一长串的替代品很难维持。反之!你只是不把所有的工作都放在那里,而是从那里调用单独的方法。
  • 是的,@5YrsLaterDBA。 @user unknown - 在分析器告诉我关心之前,我不会关心 20-40 次不必要检查对性能的影响,但是如果您可以编写更易于维护并避免不必要工作的更简洁的代码,您为什么不呢?当然,权衡是一个 if-else 检查与一个匿名类的额外分配。
  • 不要发明 api - 没有 JLabel.addActionPerformed,实际上 Swing 中的任何地方都没有这样的方法
【解决方案2】:

错误的替代方案:问题不是匿名类与长而大的 if-else 构造(您可以很容易地在前者中使用后者)。问题是是否有一个语义强大的类(匿名与否),它只完成一项工作,是唯一一个完成它并且完全完成它的类。毕竟,我们在 OO 领域 ;-)

所以:严格禁止任何 if-then-else 结构。

【讨论】:

  • 那么,您是如何编写 actionPerformed 代码的?选项2?
  • 好的,我明白了,您将使用 Actions 而不是 ActionEvent 和 ActionListenser。
【解决方案3】:

我使用第三个选项,我编写了自己的 Manager,通过注解直接将方法绑定到 JButtons。

我将它作为一个开源项目提供,你可以在https://github.com/MarkyVasconcelos/Towel/wiki/ActionManager查看它

优点是您不需要实现任何 ActionListener,也不需要匿名内部类。

所有动作都在你的类的方法中。

【讨论】:

  • 似乎不太好理解,我需要赶上那些新的java特性。
  • 这有点令人困惑,因为我也使用@Bindables 注释。但是你唯一需要学习的是@Action,它很容易使用。
  • 但是你不会失去类型安全吗? ActionListener 或/和匿名内部类有什么问题?
  • 你失去了一些类型安全的代码,以便更轻松地编写代码。 Anon-inner 类没有什么问题,但是您编写的代码量不是为案例编写的,通常,您会将逻辑写入该类,使代码为案例指定。以我的方式,您拥有方法中的代码,可以轻松地以其他方式调用并解耦逻辑以供其他用途。
【解决方案4】:

在大多数情况下,没有太大区别,建议一个优于另一个。

我会说:如果情况相似,请将它们放在一起,但只是从那里调用适当的方法:

    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

这样,您可以轻松地调用方法,独立于事件,可能来自测试框架,或者用于某些撤消/重放。共同的模式是显而易见的。

在极少数情况下,您可能会对取消注册单个事件和独立来源感兴趣。然后,每个 ActionEvent 的单个侦听器似乎更适合。

从纯粹的 OOP 角度来看,我认为每个 Button 单个侦听器(例如)更直接,并且从不成熟的优化愿望来看,我对 20 或 40 个 ActionListener 感到不舒服,但在我理性的时候,我不相信 40 个 ActionListener 会产生可衡量的影响。但是它们会弄乱你的文件系统和 IDE 浏览器,所以我想最终有一个合理的理由来保持低侦听器的数量。

一个普通的监听器很容易在按钮工厂中使用:

    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");

添加新按钮的位置和方法非常简单明了。我觉得它非常易于维护。

【讨论】:

  • 我使用的方式与您的按钮工厂非常相似。节省大量代码,易于维护。
  • 没办法,忘掉那些程序性遗留问题——即使 Swing 中的内部代码可以做到这一点……当我们这样做的时候,不要使用 ActionListeners,使用 Actions而是
  • 你有论据来支持你的主张,还是只是强烈的意见?
猜你喜欢
  • 2016-06-14
  • 2018-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-21
  • 2021-12-23
  • 2014-03-10
  • 1970-01-01
相关资源
最近更新 更多