2011-03-27 26 views
11

¿Hay ventajas o inconvenientes para la creación de una clase anidada que implementa ActionListener:clase anidada vs implementos ActionListener

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

frente a la implementación de ActionListener en la clase principal en sí:

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

que he visto ambos ejemplos con bastante frecuencia, y solo quiero saber si hay una 'mejor práctica'.

+0

Vea también [Ventajas de las clases anidadas] (http://stackoverflow.com/questions/5085157). – trashgod

Respuesta

3

Si la clase Foo no tiene otra responsabilidad que encapsular este botón, entonces la primera solución es más o menos correcta.

Sin embargo, tan pronto como Foo recibe más "cosas" que tiene que escuchar, se vuelve complicado. Prefiero la segunda solución ya que es más explícita y tiene una mejor escalabilidad.

Una solución aún mejor puede ser crear una clase interna anónima.

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

Creo que el primer enfoque es mejor, ya que su clase tendrá un código separado para la acción de manejo. Y, por lo general, también la composición es mejor que la herencia, por lo que una clase debería extender una clase o implementar una interfaz solo si realmente lo es: un súper tipo.

También para mantenimiento, digamos que la clase Foo tiene un nuevo requisito para escuchar otro tipo diferente de eventos y luego realizar una acción, en ese caso también se puede modificar fácilmente la primera clase.

Si no estoy preocupado por el mantenimiento, preferiría ir a una clase anónima.

+0

por favor ver respuesta como respuesta –

3

Por lo general, desea utilizar una clase anidada o incluso anónima en lugar de exponer ActionListener a la API de la clase adjunta. (clase pública Foo implementa ActionListener -> Javadoc indicará que Foo es un ActionListener, aunque esto suele ser solo un detalle de implementación -> malo)

10

@Ankur, puede seguir utilizando clases internas anónimas como sus oyentes y tener un clase de control independiente y, por lo tanto, tiene un código que es bastante fácil de mantener, una técnica que me gusta usar un poco. Por ejemplo:

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"); 
    } 
} 
Cuestiones relacionadas