提问者:小点点

在Java中组织GUI和ActionListener的代码[重复]


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

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

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


共3个答案

匿名用户

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

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

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

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

只是提一下,因为在sun/oracle教程中有一些例子:尽量避免使用视图类本身实现侦听器接口。如果你只有一个侦听器,这可能是可以的,但是对于来自多个来源的具有不同行为的多个事件,这在大多数情况下是可怕的。

匿名用户

代码风格可能是个人品味的问题,但现代文献表明不仅仅如此。让清洁代码中的类一章为您指明道路。

班级应该很小!

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

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

问题在于,我们中的太多人认为,一旦程序运行起来,我们就完蛋了。我们没有转向另一个关心组织和整洁的问题。我们转向下一个问题,而不是回到过去,将过度填充的类分解成具有单一职责的解耦单元。与此同时,许多开发人员担心,大量的小型、单一用途的类会使理解更大的图景变得更加困难。他们担心,他们必须从一个类导航到另一个类,才能弄清楚更大的工作是如何完成的。然而,一个有许多小类的系统并不比一个有几个大类的系统有更多的活动部件。在只有几个大类的系统中,也有同样多的东西需要学习。所以问题是:你希望你的工具被组织成工具箱,里面有许多小抽屉,每个小抽屉都包含定义良好、标记良好的组件?还是你想要几个抽屉,把所有东西都扔进去?

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

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

匿名用户

Java和摇摆鼓励许多小对象,如听众和动作。这是很多样板,但这就是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对象都可以访问这些操作。

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