2011-01-15 14 views
8

tuvimos un debate en el trabajo sobre lo que es la mejor práctica para el uso de los oyentes en Java: si la lógica escucha debe permanecer en la clase anónima, o que debería estar en un método separado, por ejemplo:Java: ¿dónde debería poner código de lógica de oyente anónimo?

button.addActionListener(new ActionListener() { 
    public void actionPerformed(ActionEvent e) { 
     // code here 
    } 
}); 

o

button.addActionListener(new ActionListener() { 
    public void actionPerformed(ActionEvent e) { 
     buttonPressed(); 
    } 
}); 

private void buttonPressed() { 
    // code here 
} 

¿Cuál es la forma recomendada en términos de legibilidad y mantenibilidad? Prefiero mantener el código dentro del oyente y solo si se vuelve demasiado grande, conviértalo en una clase interna. Aquí supongo que el código no está duplicado en ningún otro lado.

Gracias.

Respuesta

4

Mi regla autoimpuesta es:

  1. Si el oyente tiene más de 2 métodos, crear una clase llamada.
  2. Si el oyente abarca más de 10 líneas, cree una clase con nombre.

Bastante simple, fácil de seguir y produce un código más o menos legible. Pero debo admitir que nunca pensé en lo que muestra tu ejemplo.

+0

Algunas buenas reglas generales. 1+ –

+1

Tiendo a utilizar una clase interna con nombre, y tienden a crear aquellos también para oyentes más pequeños si hay muchos de ellos para evitar la ofuscación del código durante el registro. Entonces ese sería un tercer criterio para mí. – extraneon

1

En mi opinión personal, "depende". Si el oyente solo debe agregarse a un solo componente, es muy simple y es una parte integral de la GUI, entonces una clase interna anónima funcionaría bien. Si el oyente es complejo, se agregará a múltiples componentes, tendrá su propio estado por separado, luego una clase autónoma separada es mejor. En el medio está la clase interna privada. HTH.

Editar: Mi mal. Estaba respondiendo una pregunta diferente: usar o no una clase separada para un oyente. En cuanto a si mantener un código interno dentro de la clase versus en un método, estoy de acuerdo con el otro póster, dependerá del tamaño y la complejidad del código del oyente.

2

Esta pregunta está parcialmente respondida aquí:

Is there a better practice for listeners

También no les gusta la forma Anónimo por dos razones:
1) no se puede fácilmente volver a utilizar el código de lo que puede encontrar que tiene código duplicado después de un tiempo 2) Creo que rompe la lectura del código (otros no están de acuerdo ... el gusto personal). Creo que todos estarían de acuerdo en que si estás haciendo más de 5-10 líneas, una clase interna anónima no es una buena idea (diría que más de 2 es demasiado).

+0

+1 - No puede reutilizar el código en un método anónimo. – jmort253

+0

Claro que puedes. Solo obtenga al oyente desde el botón y envuélvalo en otro oyente :) Perfecta reutilización (aunque no se puede mantener :) – extraneon

+1

Claro que solo puede reutilizar la instancia. Action action = new Action ("Go") {...}, luego puede asignarlo a un botón, menú o ActionMap. No hay problema con la reutilización al reutilizar la instancia. También puede eliminarlo de los oyentes también. – chubbsondubs

1

Si alguna vez necesitará el método buttonPressed() que se accede desde cualquier lado de la clase interna anónima, a continuación, utilizar un método. De lo contrario, simplemente colocando el código dentro de actionPerformed().

+0

De acuerdo. Agradable y fácil de lograr con refactorización en IDEs. – Xorty

1

En mi experiencia personal, es mejor seguir el patrón MVC. De esta forma, hay una clase separada que representa un modelo, que crea todas las acciones relevantes, los oyentes de acción, etc. Es preferible que las acciones se representen como campos de clase final, que se instancian en el constructor.

Por ejemplo:

public class Model { 
    private final Action buttonAction; 
    ... 

    public Model(final IController controller) { 
     buttonAction = createButtonAction(controller); 
     ... 
    } 

    private Action createButtonAction(final IController controller) { 
     Action action = new Action("Action") { 
      public void actionPerformed(final ActionEvent e) { 
       // do the required action with long running ones on a separate Thread 
       controller.run(); 
      } 
     }; 
     action.set...// other initialisation such as icon etc 
     ... 
     return action; 
    } 
    ... 

    public Action getButtonAction() { 
     return buttonAction; 
    } 
} 

La vista también está representada por una clase separada, que toma el modelo como su parámetro de constructor, donde el botón de instanciación real tiene lugar. Por ejemplo:

public class View extends JPanel { 
    public View(final Model model) { 
     ... 
     JButton button = new JButton(model.getButtonAction(); 
     ... 
    } 
} 

Con este enfoque es muy conveniente para implementar la lógica de actionPerformed como parte de la clase anónima ya que tiene muy poco para ser reutilizado. Toda la lógica está encapsulada en el controlador, por lo que las acciones sirven realmente como un envoltorio alrededor de la llamada del controlador que se utilizará como modelo para un botón.

0

Sí, depende en gran medida de lo que estás tratando de hacer. Creo que las clases internas anónimas han recibido una mala reputación debido a dos mitos. Uno no puede reutilizar el código anónimo. Y dos, pérdidas de memoria. Pero estos se arreglan fácilmente con un enfoque simple. Guarde una referencia a la instancia. Para compartir el código simplemente crea una referencia a la clase interna anónima.

Action action = new AbstractAction("Open") {...}; 
JButton button = new JButton(action); 
JMenuItem menuItem = new JMenuItem(action); 
panel.getActionMap().put("openFile", action); 

Ahora puede reutilizar esa acción en varios componentes. Para el problema posterior de pérdidas de memoria puede usar esa referencia para anular el registro, o la segunda y más simple opción es WeakListeners. Los WeakListeners tienen la ventaja de que no necesitan administrarse después de su creación.

En cuanto al estilo, considero que los oyentes anónimos son bastante útiles y, en algunos casos, más fáciles de leer cuando se trata de enhebrar en Swing porque mantienen el código en un método (invokeLater, executeInBackground, etc.). Cuando usted oye delegados a un método de instancia creo que separa el código donde no puede leer lo que sucedió antes del oyente y la lógica asociada con el oyente en una pantalla. Tienden a separarse, y es más difícil de seguir.

Algo a tener en cuenta es que si usa ActionMaps, la mayoría de las pérdidas de memoria desaparecerán asociadas con la escucha del teclado. Lamentablemente, cosas como los oyentes de enfoque o los que están registrados en los sistemas centrales siguen siendo un problema. (De nuevo WeakListeners son geniales aquí). Y ya tiene un lugar para mantener la acción con cada componente, por lo que no es necesario crear variables de instancia adicionales para mantenerlo. Si necesita reutilizar en dos componentes (por ejemplo, en una barra de menú y en un control), cree una clase por separado.

Cuestiones relacionadas