Должен ли ваш класс реализовывать ActionListener или использовать объект анонимного класса ActionListener

Как лучше всего реализовать интерфейс java.awt.event.ActionListener?

Пусть ваш класс реализует ActionListener и добавляет это как ActionListener:

class Foo implements ActionListener{

    public Foo() {
        JButton button = new JButton();
        button.addActionListener(this);
    }

    public void actionPerformed(ActionEvent e) {

    }
}

Или добавьте объект анонимного класса ActionListener:

class Foo{

    public Foo() {
        JButton button = new JButton();
        button.addActionListener(new ActionListener() {     
            public void actionPerformed(ActionEvent e) {

            }
        });
    }
}

person elias    schedule 11.07.2012    source источник


Ответы (3)


Некоторые (жанетт/клеопатра) говорят, что почти никогда не используют ActionListener, а вместо этого используют действия, такие как AbstractAction. Почти всегда плохой вариант, когда ваш GUI-класс реализует слушателей, поскольку это нарушает принцип единой ответственности и усложняет поддержку и расширение вашего кода, поэтому я настоятельно призываю вас не делать этого.

Так, например, внутренний класс для этого:

import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;

class Foo {

   public Foo() {
       JButton button = new JButton(new ButtonAction("Action", KeyEvent.VK_A));
   }

   private class ButtonAction extends AbstractAction {
      public ButtonAction(String name, Integer mnemonic) {
         super(name);
         putValue(MNEMONIC_KEY, mnemonic);
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         System.out.println("button pressed");
      }
   }

}
person Hovercraft Full Of Eels    schedule 11.07.2012
comment
+1 Для AbstractAction и Single Responsibility Principle. - person Eng.Fouad; 11.07.2012
comment
Хорошо, но кажется более сложным (с точки зрения поддержки кода) и более трудным для чтения. Или я ошибаюсь? - person elias; 11.07.2012
comment
По мере знакомства с ним становится легче читать. Я использовал его, когда пытался поддерживать хорошо разделенный шаблон MVC, и мой элемент управления вводил действия в мои JButtons. - person Hovercraft Full Of Eels; 11.07.2012
comment
И не забывайте, легче проверить. Вы можете просто протестировать класс действий, когда он не привязан к вашему пользовательскому интерфейсу. - person Robin; 12.07.2012
comment
Связанный пример — и конструктивный обзор в комментариях — здесь. - person trashgod; 12.07.2012
comment
@HovercraftFullOfEels, как вы управляете зависимостями, когда действие используется двумя разными контроллерами? Вы бы создали отдельные действия? (Я понимаю, что цель состоит в том, чтобы использовать одно и то же действие в разных контекстах). И мне могут понадобиться знания о моем представлении или моем контроллере. Я создал действия, используемые в разных контроллерах, но у меня были серьезные проблемы с зависимостями, поэтому я вернулся к внутреннему классу в представлении. - person Rytek; 23.04.2014

Второй вариант (анонимный класс), безусловно, лучше, другой вариант — иметь вложенный класс внутри Foo.

Я бы не стал использовать первый вариант по двум причинам:

  • Пользователи Foo не должны знать, что он реализует ActionListener.
  • Вы не можете реализовать два разных слушателя в одном классе.
person casablanca    schedule 11.07.2012
comment
Я бы проголосовал за этот ответ по первой причине, но вторая причина просто неверна, имхо. Вы можете проверить источник ActionEvent и выбрать путь кода, который вам следует выбрать. Является ли это элегантным решением, это другой разговор, но это, безусловно, возможно. - person Robin; 12.07.2012
comment
@Robin: Ты прав, но я не об этом. Я имел в виду, что нельзя реализовать ActionListener дважды в одном и том же классе. - person casablanca; 12.07.2012

По-разному. Если вы хотите повторно использовать ActionListener в нескольких компонентах, первый вариант лучше. Если ActionListener будет ассоциироваться только с одной кнопкой, второй вариант подойдет.

Как правило, вы должны создать отдельный класс (или внутренний класс), если ожидаете некоторого роста в проекте. Нет необходимости в Foo для реализации ActionListener.

person Rob Wagner    schedule 11.07.2012
comment
Наличие класса графического интерфейса, реализующего ActionListener, предназначено только для игрушечных программ. Поскольку он спрашивает о лучших практиках, это бесполезно ни при каких обстоятельствах. - person Hovercraft Full Of Eels; 11.07.2012