Вложенный класс против реализует ActionListener - PullRequest
11 голосов
/ 27 марта 2011

Существуют ли какие-либо преимущества или недостатки при создании вложенного класса, реализующего ActionListener:

public class Foo{
    Foo(){
        something.addActionListener(new ButtonListener());
    }
    //...
    private class ButtonListener implements ActionListener{
        public void actionPerformed(ActionEvent e){
            //...
        }
    }
}

по сравнению с реализацией ActionListener в самом основном классе:

public class Foo implements ActionListener{
    Foo(){
        something.addActionListener(this);
    }
    //...
    public void actionPerformed(ActionEvent e){
        //...
    }
}

Я видел обапримеры довольно часто, и просто хочу знать, есть ли «лучшая практика».

Ответы [ 4 ]

10 голосов
/ 27 марта 2011

@ Анкур, вы все еще можете использовать анонимные внутренние классы в качестве своих слушателей и иметь отдельный автономный класс управления и, таким образом, иметь вполне поддерживаемый код, метод, который мне нравится использовать немного. Например:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class AnonymousInnerEg {
   private static void createAndShowUI() {
      GuiPanel guiPanel = new GuiPanel();
      GuiControl guiControl = new GuiControl();
      guiPanel.setGuiControl(guiControl);

      JFrame frame = new JFrame("AnonymousInnerEg");
      frame.getContentPane().add(guiPanel);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      java.awt.EventQueue.invokeLater(new Runnable() {
         public void run() {
            createAndShowUI();
         }
      });
   }
}

class GuiPanel extends JPanel {
   private GuiControl control;

   public GuiPanel() {
      JButton startButton = new JButton("Start");
      startButton.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            if (control != null) {
               control.startButtonActionPerformed(e);
            }
         }
      });
      JButton endButton = new JButton("End");
      endButton.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            if (control != null) {
               control.endButtonActionPerformed(e);
            }
         }
      });

      add(startButton);
      add(endButton);
   }

   public void setGuiControl(GuiControl control) {
      this.control = control;
   }


}

class GuiControl {
   public void startButtonActionPerformed(ActionEvent ae) {
      System.out.println("start button pushed");
   }

   public void endButtonActionPerformed(ActionEvent ae) {
      System.out.println("end button pushed");
   }
}
5 голосов
/ 27 марта 2011

Я думаю, что первый подход лучше, так как у вашего класса будет отдельный код для обработки действий. И обычно состав также лучше наследования, поэтому класс должен расширять класс или реализовывать интерфейс только в том случае, если это действительно супер тип.

Также для удобства сопровождения, скажем, у класса Foo есть новое требование - прослушивать события другого типа и затем выполнять действие, в этом случае также легко можно изменить первый класс.

Если я не беспокоюсь за ремонтопригодность, я бы предпочел пойти на анонимный класс.

3 голосов
/ 27 марта 2011

Обычно вы хотите использовать вложенный или даже анонимный класс, а не выставлять ActionListener API включающего класса. (открытый класс Foo реализует ActionListener -> Javadoc сообщит, что Foo является ActionListener, хотя обычно это просто деталь реализации -> плохая)

3 голосов
/ 27 марта 2011

Если класс Foo не несет никакой другой ответственности, кроме инкапсуляции этой кнопки, тогда первое решение вроде бы нормально.

Однако, как только Foo получает больше «чего-то», что он должен слушать, он становится грязным. Я предпочитаю второе решение, поскольку оно более явное и лучше масштабируемое.

Еще лучшим решением может быть создание аномимного внутреннего класса.

public class Foo{
    Foo(){
        something.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e){
                //...
            }
        });
    }
}
...