# Eventhandler: innere Klassen vs. "normale Klassen"



## AKST (25. September 2004)

Hallo Leute,

ich als Java-Anfänger frage mich folgendes:

Wie bevorzugt ihr eure z.B. ActionListener umzusetzen. Mit (anonymen) Inneren Klassen oder normalen Klassen. 

Ich finde normale Klassen (implements ActionListener) viel übersichtlicher auch wenn man dieser im Konstruktor das jeweilige Fenster übergeben muss. 
Ich frage deshalb, weil ich es oft in Büchern, in Foren oder bei Gui-Buildern sehe, dass innere Klassen  verwendet werden.
Ich finde diesen Programmierstil aber unschön.


----------



## Snape (27. September 2004)

Moin,
ich halte eine eigene, von ActionListener abgeleitete Klasse oder auch eine implementierende Klasse für unpraktisch. Zumindest kenne ich keinen Fall, wo es Sinn macht. Grund: Es wird lediglich die Methode actionPerformed() implementiert. Und ich sehe keinen Sinn, warum nicht genau das Objekt bzw. die Komponente, die reagieren soll, eine eigene actionPerformed() bekommen sollte. Nimmst Du hingegen ein Frame mit verschiedenen Komponenten als ActionListener, musst Du jedes Mal zunächst herausfinden, welche Komponente das Event ausgelöst hat.


----------



## Christian Fein (27. September 2004)

> _Original geschrieben von AKST _
> *
> Wie bevorzugt ihr eure z.B. ActionListener umzusetzen. Mit (anonymen) Inneren Klassen oder normalen Klassen.
> *



Das kommt auf die Situation, grösse des Projektes, usw an.  



> *
> Ich frage deshalb, weil ich es oft in Büchern, in Foren oder bei Gui-Buildern sehe, dass innere Klassen  verwendet werden.
> Ich finde diesen Programmierstil aber unschön. *



In Bücher kommt das fast immer so vor, weil Listener das Paradebeispiel ist um dem Leser den Gebrauch von anonymen Klassen beizubringen.


----------



## Snape (27. September 2004)

Übrigens noch eine Ergänzung:
Anonyme Klassen sind etwas anderes als innere Klassen!
Nicht dass hier Verwechslungen aufkommen.


----------



## AKST (27. September 2004)

@Snape,

es stimmt zwar, dass eine anonyme Klasse für einen ActionListener oft nur die Methode actionPerformed() besitzt wenn ich in dieser aber etliche Actions von ettlichen Buttons und Menüitems über getActioncommand abfragen muss, dann sieht der Code meiner Meinung nach ziemlich unsauber aus. 
Ich könnte natürlich in dieser Methode das ActionEvent an eine andere Methode weitergeben und dort alles managen, dann wäre der Actionlistener wirklich klein.


----------



## Vincentius (27. September 2004)

> _Original geschrieben von AKST _
> *Ich könnte natürlich in dieser Methode das ActionEvent an eine andere Methode weitergeben und dort alles managen, dann wäre der Actionlistener wirklich klein. *


In dem Fall ist es besser, wenn die Klasse, wo Du den *ActionListener* brauchst selbst der *ActionListener* ist und implementiert die Methode *actionPerformed()*.


----------



## Christian Fein (27. September 2004)

> _Original geschrieben von AKST _
> *@Snape,
> 
> es stimmt zwar, dass eine anonyme Klasse für einen ActionListener oft nur die Methode actionPerformed() besitzt wenn ich in dieser aber etliche Actions von ettlichen Buttons und Menüitems über getActioncommand abfragen muss, dann sieht der Code meiner Meinung nach ziemlich unsauber aus.
> Ich könnte natürlich in dieser Methode das ActionEvent an eine andere Methode weitergeben und dort alles managen, dann wäre der Actionlistener wirklich klein. *



MenuItems und Buttons die die selbe Funktionalität besitzen (z.b Speichern) sollten auch ein Object der selben klasse als Listener nutzen.


----------



## Snape (27. September 2004)

Jo, und unübersichtlich wird das nicht, wenn Du jeder Komponente einen eigenen ActionListener verpasst.


```
jbOK.addActionListener(new java.awt.event.ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				jbOK_actionPerformed(e);
			}
		});
		jbCancel.addActionListener(new java.awt.event.ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				jbCancel_actionPerformed(e);
			}
		});
```

usw.


----------



## AKST (27. September 2004)

Hmm, vielleicht habeb wir uns ja missverstanden. Ich meine es so, wenn ich ein JFrame habe auf dem sich ca. 10 Buttons befinden, dann habe ich für dieses JFrame nur einen Actionlistener und füge jedem Button diesen ActionListener hinzu.

Wenn ich nun statt einer "normalen Klasse" eine anonyme Klasse verwende, dann müsste ich für jeden Button das ActionCommand abfragen, was ich etwas unübersichtlich finden würde, da die anonyme Klasse versetzt mitten im Quellcode des JFrames sitzt. 
Deshalb meinte ich, dass ich in der actionPerformed-Methode nur eine Methode (z.B.: "events_managen(event)") aufrufe und dieser das ActionEvent übergebe. In dieser Methode würde ich dann alle Actioncomands in if-Blöcken abfragen und bearbeiten. 

Wäre das unsauber?
Ist überhaupt etwas daran auszustezen wenn ich immer nur einen Actionlistener pro Frame nehme und anhand des ActionCommands das aufrufende Oberflächenelement identifiziere?


----------



## Christian Fein (27. September 2004)

> _Original geschrieben von AKST _
> *
> Wäre das unsauber?
> Ist überhaupt etwas daran auszustezen wenn ich immer nur einen Actionlistener pro Frame nehme und anhand des ActionCommands das aufrufende Oberflächenelement identifiziere? *



Ja sehr unsauber.

Du müsstest für jede Änderrung an einem Button eine Klasse editieren die du für alle anderen auch nutzt.

Was stört dich daran jede Aktion in einer eigenen Klasse zu kapseln?

Wenn du dann eine Aktion umändern willst brauchst du nur jene Klasse austauschen und nicht noch in einer Methode rumwurschteln.


----------



## AKST (27. September 2004)

Vielleicht ist dieser Stil doch ganz gut:


```
jbOK.addActionListener(new java.awt.event.ActionListener(){
			
  public void actionPerformed(ActionEvent e){
    jbOK_actionPerformed(e);
  }
});

jbCancel.addActionListener(new java.awt.event.ActionListener(){

  public void actionPerformed(ActionEvent e){
    jbCancel_actionPerformed(e);
  }
});
```


----------



## Snape (27. September 2004)

Bestimmt ist der gut. 
Ich/Wir implementiere fast nur so.


----------



## Thomas Darimont (27. September 2004)

Hallo!



> ```
> jbOK.addActionListener(new java.awt.event.ActionListener(){
> 
> public void actionPerformed(ActionEvent e){
> ...



... für jede Componente eine eigene Anonyme Klasse UND noch eine Methode für jede Componente ...?!

Also wenns bei mir mehr als 5 Componenten gibt die auf ActionEvents 
reagieren sollen dann erstelle ich lieber eine Inner Klasse die das ActionListener Interface implementiertt. Dort sieht das weitere dann Ungefähr so aus:


```
import java.awt.Component;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

public class EventHandlingDemo extends JFrame {

	private JButton btnOk, btnCancel, btnExit, btnAction0, btnAction1;

	public EventHandlingDemo() {
		super("EventHandlingDemo");
		setDefaultCloseOperation(EXIT_ON_CLOSE);

		Container c = getContentPane();
		c.setLayout(new FlowLayout());

		final ActionListener listener = new ActionHandler();

		c.add((btnOk = new JButton("btnOk") {
			{
				addActionListener(listener);
			}
		}));

		c.add((btnCancel = new JButton("btnCancel") {
			{
				addActionListener(listener);
			}
		}));
		c.add((btnExit = new JButton("btnExit") {
			{
				addActionListener(listener);
			}
		}));
		c.add((btnAction0 = new JButton("btnAction0") {
			{
				addActionListener(listener);
			}
		}));
		c.add((btnAction1 = new JButton("btnAction1") {
			{
				addActionListener(listener);
			}
		}));

		pack();
		setVisible(true);
	}

	public static void main(String[] args) {
		new EventHandlingDemo();
	}

	class ActionHandler implements ActionListener {

		public void actionPerformed(ActionEvent e) {
			Object o = e.getSource();
			
			if(o == btnOk){ 
				JOptionPane.showMessageDialog((Component)o,"btnOk was pressed!");
			}else if(o == btnCancel){
				JOptionPane.showMessageDialog((Component)o,"btnCancel was pressed!");
			}else if(o == btnExit){
				JOptionPane.showMessageDialog((Component)o,"btnExit was pressed!");
			}else if(o == btnAction0){
				JOptionPane.showMessageDialog((Component)o,"btnAction0 was pressed!");
			}else if(o == btnAction1){
				JOptionPane.showMessageDialog((Component)o,"btnAction1 was pressed!");
			}
		}
	}
}
```

So habe ich meinen Event Code schön übersichtlich an einer Stelle und  muß  mir nicht 10 Mio. Methoden durchschauen...

Gruß Tom


----------



## Christian Fein (27. September 2004)

> _Original geschrieben von Thomas Darimont _
> *
> 
> So habe ich meinen Event Code schön übersichtlich an einer Stelle und  muß  mir nicht 10 Mio. Methoden durchschauen...
> *



Finde ich nicht so schön.  Wenn du z.b einerseits den Button Save und anderseits den Menupunkt Save hast, kannst du nicht einfach eine SavePressedListener ohne codezugriff zuordnen.

Meiner Meinung nach besser


```
public class SaveActionListener extends ActionListener() {
     public void actionPerformed(ActionEvent e){
        // speichern
      }
  }

 ... 
    menuSave.addActionListener(new SaveActionListener());
    buttonSave.addActionListener(new SaveActionListener());
```


----------



## Thomas Darimont (27. September 2004)

Kommt darauf an...

wenn der Codeanteil der hinter ActionPerformed des jeweiligen Controls liegt in exorbitante Dimensionen ansteigt ist es natürlich besser eine eigene Klasse dafür zu kreieren. Falls jedoch nur 2-3 Anweisungen abzuarbieten sind finde ich den Innere Klassen Ansatz besser.

Gruß Tom


----------



## Christian Fein (27. September 2004)

> _Original geschrieben von Thomas Darimont _
> *Kommt daruf an...
> 
> wenn der Codeanteil der hinter ActionPerformed des jeweiligen Controls liegt in exorbitante Dimensionen ansteigt ist es natürlich besser eine eigene Klasse dafür zu kreieren. Falls jedoch nur 2-3 Anweisungen abzuarbieten sind finde ich den Innere Klassen Ansatz besser.
> ...



Womit meine 1. Aussage in diesem Thread wieder passen würde



> Das kommt auf die Situation, grösse des Projektes, usw an.



  *ich muss das letzte Wort haben*


----------



## AKST (27. September 2004)

Thomas seine Lösung ist doch ähnlich zu meiner. Er fragt innerhalb einer ActionListener-Klasse die aufrufende Klasse (JButton1, JButton2...) ab und ordnet dann die Methode zu.
Ich muss ehrlich sagen, dass es mir nicht wirklich einleuchten will, dass es übersichtlicher ist jedem Oberflächenelement einen extra ActionListener  
zu spendieren als mehrere Buttons in einem Listener zu bearbeiten. Da man ja in ActionListenern so wenig Code wie möglich schreiben soll (es werden nur Methoden aufgerufen), ist es doch garnicht so verkehrt das in einer Klasse zu machen (sei es nun eine innere, oder äußere Klasse). 

P.S. ich als Java-newbie lasse mich aber gerne eines besseren belehren....


----------

