2011-02-22 19 views
11

Para proyectos de tamaño decente, me han dicho que cuando tiene clases que amplían JPanels, la mejor práctica es utilizar clases anidadas para implementar los oyentes. Por ejemplo, podría tener una clase FactoryScreen que amplíe JPanel, y tenga una clase anidada FactoryScreenBrain que implemente todos los oyentes necesarios.Ventajas de las clases anidadas para los oyentes en GUI

Nunca he podido obtener una buena explicación de los beneficios o desventajas específicos para encapsular mis clases de esta manera, y hasta ahora siempre he tenido clases que amplían JPanel e implementan oyentes. ¿Alguien puede proporcionarme alguna orientación sobre esto?

+0

Extender innecesariamente un 'JPanel' (o' JFrame' o 'Thread') no es una buena práctica. Pero entonces, la programación GUI y las buenas prácticas no tienden a cumplir –

Respuesta

8

Tener clases internas para sus oyentes hace que el propósito de todos los oyentes sea muy claro. También a veces puede evitar muchas verificaciones a expensas de un poco más de codificación.

Si usted tiene un panel

public class MyPanel extends JPanel implements ActionListener 
... 
    button1.addActionListener(this); 
    button2.addActionListener(this); 
    checkbox1.addActionListener(this); 
    timer3.addActionListener(this); 

    public void actionPerformed(ActionEvent e) 
    { 
     if(e.getSource() == button1) 
     else... 
     ... //potentially many elses 
    } 

que es muy difícil de ver exactamente lo que está pasando en su actionPerformed porque maneja tantos eventos diferentes a la vez. Que tiene un panel:

public class MyPanel extends JPanel 
... 
    button1.addActionListener(new ButtonListener()); 
    button2.addActionListener(new ButtonListener()); 
    checkbox1.addActionListener(new CheckBoxListener()); 
    timer3.addActionListener(new TimerListener()); 

    private class TimerListener implements ActionListener 
    { 
     public void actionPerformed(ActionEvent e) 
     { 
      //do stuff related only to timers 
     } 
    } 

Ahora bien, si el temporizador tiene un problema que se puede identificar fácilmente la clase con el problema.

Aún más importante, a gran escala, hace que su código sea más legible. Si alguien más quiere trabajar en esta clase y necesitan arreglar el manejo de eventos con el temporizador, no tienen que buscar en su ifs para encontrar la parte con la lógica del temporizador.

6

Creo que cualquier cosa es mejor que tener una clase que amplíe un Componente de oscilación e implemente un oyente, ya que da a la clase demasiadas responsabilidades dispares y crea una para los temidos oyentes de la placa de conmutación. Intento usar oyentes internos anónimos que invocan métodos de una clase de control separada. De esa forma, divido las responsabilidades y puedo probar más fácilmente los comportamientos de cada clase de forma aislada.

Buena pregunta, por cierto.

+3

Sí. Es la separación de las preocupaciones lo que es la gran victoria. La clase interna anidada (o anónima) tiene una y solo una tarea por hacer. Hace que el seguimiento de todo su comportamiento sea muy fácil. Si tiene un panel que tiene docenas de objetos llamando a un método actionPerformed, por ejemplo, hace que ese método sea más grande, más difícil de entender o de mantener. Si altera ese método para un propósito, por ejemplo, entonces corre el riesgo de afectar accidentalmente las otras responsabilidades manejadas por ese método. – Kaffiene

+0

Gracias por el comentario, y posiblemente por la votación positiva. Si fueras tú, debes empujarme más de 3000. ¡Grats! :) –

2

Si extiende un componente e implementa uno o más oyentes, es tentador agregar los oyentes en el constructor. Esto potencialmente expone una referencia a un objeto construido de manera incompleta, a veces llamado escaped this. Trabajar exclusivamente en EDT mitiga el riesgo; pero una clase interna anónima puede reducirlo aún más. Los problemas de la reflexión o indirect exposure permanecen.

+0

No estoy seguro de si el uso de una clase interna anónima se deshace del problema. Más adelante en la página http://www.ibm.com/developerworks/java/library/j-jtp0618.html#3 se describe cómo una clase interna anónima aún puede sufrir condiciones de carrera si una subclase depende de los eventos. La única forma en que puedo pensar para evitar esto realmente puede ser hacer que tu clase GUI sea definitiva (lo cual es definitivamente viable en algunos casos) pero el enlace realmente no detalla otros métodos para resolver esto ... – donnyton

+0

Buen punto; no es una panaceaComo señala Joshua Bloch, "diseña y documenta por herencia o, de lo contrario, prohíbe". – trashgod

+0

Me gustaría entender el voto negativo, por lo que puedo aclarar la respuesta. – trashgod

Cuestiones relacionadas