4

我是 Java 新手,想知道如何ActionListener在我的项目中实现代码。我知道内部类和ActionListener接口的实现,但是走这条路会使代码看起来比它应该的更混乱。

我会写另一个ActionCode实现ActionListener和扩展 GUI 的类,或者你会建议什么道路,为什么?

您对此有什么最佳实践建议,我在哪里可以找到这些指南?(JavaDoc 似乎解释了ActionListeners 的基本实现,但似乎没有任何模型如何组织大/中型项目)。

4

3 回答 3

3

在我看来,没有“最好”的方法。甚至 sun/oracle 教程中的代码示例也使用不同的方式来实现侦听器。

根据我的经验,一个好的方法是:

  • 使用匿名实现:人们知道这种模式并且会很快认出它。如果有通用的做事方式,它可以帮助读者理解代码
  • 有一个特殊的方法,它只处理监听器(例如private void addListeners()):同样,这有助于每个人识别它并知道在哪里搜索所有逻辑
  • 让听众保持简单。这意味着少于 5-10 行代码。如果您需要更复杂的逻辑,请调用方法。
  • 保持听众人数较少。如果您需要 > 50 个侦听器,您可能应该重构您的视图。如果你需要超过 10 个,你可以考虑重构。

除了这些一般要点之外,总会有例外。就像你有很多具有相同行为的组件一样,你可以编写一个带有 switch/case 的通用侦听器。(典型示例:计算器按钮或菜单按钮)。
或者,如果您对多个组件有相同的逻辑,则可以使用特定的类。
等等。

顺便提一下,因为 sun/oracle 教程中有一些示例: 尽量避免使用视图类本身实现侦听器接口。如果您只有一个侦听器,这可能没问题,但大多数情况下,对于来自具有不同行为的多个源的多个事件来说,这很糟糕。

于 2012-12-19T00:21:58.343 回答
1

代码风格可能是个人品味的问题,但现代文献表明它不止于此。让清洁代码中的类一章向您展示方法。

班级应该很小!

类的第一条规则是它们应该很小。类的第二个规则是它们应该小于这个值。不,我们不会重复函数章节中完全相同的文本。但与函数一样,在设计类时,更小是主要规则。与函数一样,我们的直接问题始终是“有多小?” 对于函数,我们通过计算物理线来测量大小。对于类,我们使用不同的度量。我们计算责任...

单一职责原则 (SRP) 指出一个类或模块应该有一个并且只有一个改变的理由。这个原则给了我们责任的定义和班级规模的指导。类应该有一个责任——一个改变的理由……

问题是我们中的太多人认为一旦程序运行我们就完成了。我们未能转向组织和清洁的另一个关注点。我们继续下一个问题,而不是返回并将过度填充的类分解为具有单一职责的解耦单元。同时,许多开发人员担心大量的小型、单一用途的类会使理解大局变得更加困难。他们担心他们必须从一个班级导航到另一个班级,以便弄清楚如何完成更大的工作。然而,一个有很多小类的系统不会比一个有几个大类的系统有更多的活动部件。在这个系统中,有几个大班要学的东西也一样多。所以问题是:您是否希望将您的工具组织成带有许多小抽屉的工具箱,每个小抽屉都包含明确定义和标记良好的组件?或者你想要几个抽屉,你可以把所有东西都扔进去?

每个相当大的系统都将包含大量的逻辑和复杂性。管理这种复杂性的主要目标是组织它,以便开发人员知道在哪里可以找到东西,并且只需要了解在任何给定时间直接影响的复杂性。相比之下,具有更大、多用途课程的系统总是会通过坚持让我们涉足许多我们现在不需要知道的事情来阻碍我们。重申前面的重点:我们希望我们的系统由许多小类组成,而不是由几个大类组成。每个小类都封装了一个职责,有一个改变的理由,并与其他几个类协作以实现所需的系统行为。

因此,基于这些启发式方法,嵌套类打破了 SRP。它们几乎不应该发生。相反,让您的 GUI 类包含它们注册的 ActionListener 的实例成员。将侦听器保存在单独的 *.listener 包中。在认为有效的地方使用接口使它们可替换(策略模式)。

于 2012-12-19T00:15:51.420 回答
0

Java 和 Swing 鼓励使用很多小对象,例如 Listeners 和 Actions。这是很多样板,但Java就是这样。对抗它没有什么好处。

内联创建匿名侦听器相当轻松:

JButton okButton = new JButton("OK");
okButton.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        ok();
    }
});

但是,您经常需要重用操作,例如将相同的操作分配给菜单和按钮。您可以将它们作为内部类放在主应用程序窗口中:

import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;


public class MainWindow extends JFrame {

    ZapAction zapAction;

    public MainWindow() {

        setSize(new Dimension(200,200));

        zapAction = new ZapAction();

        JMenuBar menuBar = new JMenuBar();
        JMenu menu = new JMenu("Foo");
        menu.add(new JMenuItem(zapAction));
        menuBar.add(menu);
        setJMenuBar(menuBar);

        JButton zapButton = new JButton(zapAction);

        add(zapButton);
    }

    public void zap() {
        // do some zapping
        System.out.println("Zap!");
        // maybe we're all done zapping?
        zapAction.setEnabled(isZappingPossible());
    }

    public boolean isZappingPossible() {
        // determine if there's zapping to be done
        return Math.random() < 0.9;
    }

    class ZapAction extends AbstractAction {
        public ZapAction() {
            super("Zap");
            putValue(AbstractAction.SHORT_DESCRIPTION, "Zap something");
            putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(
                KeyEvent.VK_Z, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
            putValue(AbstractAction.SMALL_ICON, 
                new ImageIcon(MainWindow.class.getResource("/icons/zap.png")));
            setEnabled(true);
        }
        public void actionPerformed(ActionEvent e) {
            zap();
        }
    }
}

public class Zap {
    public static void main(String[] args) {
        MainWindow mainWindow = new MainWindow();
        mainWindow.setVisible(true);
    }
}

这里ZapAction是包私有可见性。我把所有的 UI 代码放在它自己的包中(比如说org.myorg.myproject.ui)。因此,所有 UI 对象都可以访问这些操作。

在一个复杂的 Swing 应用程序中,我甚至创建了一个 UI 外观层,它为操作和将它们连接到各种控件的所有代码提供了一个很好的位置。它还为外部代码与 UI 交互提供了一个方便的地方,使 UI 代码与核心应用程序代码隔离。

于 2012-12-19T02:05:23.307 回答