# innere klassen auslagern



## Colt45 (17. Mrz 2012)

Moin, 
ich steh vor einem kleinen Problem. Ich habe eine große Controllerklasse mit etlichen inneren klassen, die die ActionEvents von verschiedenen Buttons handlen. Nun möchte ich diese inneren klassen auslagern, das Problem dabei ist, dass diese auf Instanzvariablen und Methoden der Controllerklasse zugreifen (ich will weder public instanzvariablen noch jedes mal den Controller instanziieren), und das sind in manchen inneren klassen ziemlich viele, also fällt die Option, sie als Parameter dem Konstruktor zu übergeben schonmal weg.
Hat jemand eine Idee, wie ich an dieses Problem rangehen kann, ohne massiv in die grundarchitektur einzugreifen?
Danke schonmal im Vorraus.
-Colt


----------



## Tobias (17. Mrz 2012)

Jeweils den Controller als Konstruktorargument mit übergeben.


----------



## L-ectron-X (17. Mrz 2012)

Colt45 hat gesagt.:


> Nun möchte ich diese inneren klassen auslagern,


Das macht auch Sinn. Zu viele innere Klassen sollen sich recht unperformant auswirken.



Colt45 hat gesagt.:


> (ich will weder public instanzvariablen noch jedes mal den Controller instanziieren)


Macht man beides nicht. Instanzvariablen sollten immer 
	
	
	
	





```
private
```
 deklariert werden. Der Zugriff von außen bzw. die Manipulation von Daten einer Klasse sollte immer über Methoden laufen.
Man erzeugt auch nicht jedes mal ein Controller-Objekt. Man übergibt einfach 
	
	
	
	





```
this
```
. 



Colt45 hat gesagt.:


> Hat jemand eine Idee, wie ich an dieses Problem rangehen kann, ohne massiv in die grundarchitektur einzugreifen?



Von [JAPI]AbstractAction[/JAPI] erben und 
	
	
	
	





```
actionPerformed()
```
 überscheiben?


----------



## Colt45 (17. Mrz 2012)

L-ectron-X hat gesagt.:


> Von [JAPI]AbstractAction[/JAPI] erben und
> 
> 
> 
> ...



Könntest du mir das genauer erklären, wie das mit AbstractAction funktioniert, ich hab damit noch nicht wirklich gearbeitet bzw. mich damit befasst?

Hier mal ein Beispiel, wie ich es bis jetzt gelöst habe:


```
private class UnitFormListener implements ActionListener
	{
		public void actionPerformed(ActionEvent e)
		{
			Object src = e.getSource();

                        //unitForm erbt von JFrame und ist Instanzvariable im Controller
			if(src == unitForm.getAdditionalUnitButton())
			{
                                //createUnit ist eine Methode im Controller, die wiederum           
                                //auf Instanzvariablen zugreift
				createUnit();
				unitForm.getUnitNameTextField().setText("");
				unitForm.getUnitDescriptionTextField().setText("");
			}
			else if(src == unitForm.getCancelButton())
			{
				unitForm.dispose();
			}
			else if(src == unitForm.getFinishButton())
			{
                                //viewState ist eine Hilfsvariable um zu unterscheiden, ob unitForm grad
                                //im "Neu"-Modus oder im "Bearbeiten"-Modus steht
				if(unitForm.getViewState() == 1)
				{
					unitForm.dispose();
					createUnit();
				}
				else if(unitForm.getViewState() == 2)
				{
					unitForm.dispose();
					updateUnit();
				}

			}
		}
	}
```


----------



## L-ectron-X (17. Mrz 2012)

Schau dir die Konstruktoren von [JAPI]AbstractAction[/JAPI] an. Mit dem super()-Aufruf kannst du der Basisklasse Werte zu deren Initialisierung übergeben. Auch ein Icon ist möglich.

Hier mal ein frei aus der Luft gegriffenes Beispiel zum setzen der Hintergrundfarbe einer Component.

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

public class ChooseColorAction extends AbstractAction {
   private MainPanel panel;

   public ChooseColorAction(MainPanel panel, String name) {
      super(name);
      this.panel = panel;
   }

   public void actionPerformed(ActionEvent e) {
      panel.setBackground(JColorChooser.showDialog(panel, "Hintergrundfarbe auswählen", Color.WHITE));
   }
}
```

In deinem Controller müsste in diesem Fall dann eine setBackground()-Methode implementiert sein, die die Hintergrundfarbe der entsprechenden Component setzt.
Der Code zum Einsetzen der Action in den Button sähe dann so aus:

```
chooseColorBtn = new JButton(new ChooseColorAction(this, "Hintergrundfarbe setzen"));
```


----------



## Colt45 (17. Mrz 2012)

Also grundsätzlich isses so gelöst, dass ich verschiedene Klassen habe, die von JFrame erben und die einzelnen Fenster repräsentieren, in diesen sind die JButtons instanziiert und deklariert. Was beim Klicken passieren soll, wird im Controller geregelt. Da hol ich mir mittels eines getters in der JFrame-Klasse den Button und rufe dann eine Methode im Controller auf. Ich wollte es auch vom Design her so handlen, dass ich nicht für jeden Button eine eigene AbstractAction-Klasse verwende, sondern pro Fenster, also pro JFrame einen 
	
	
	
	





```
MyJFrameListener implements Action Listener
```
.


----------



## L-ectron-X (17. Mrz 2012)

Na dann musst du für jeden JFrame Klassen schreiben, die das Interface ActionListener implementieren.
Innerhalb der Klasse verarbeitest du dann die Events der Komponenten, auf die dein Listener lauscht.

BTW: Eine Anwendung sollte nur einen JFrame haben. Die anderen Fenster sollten vom Typ JDialog und JOptionPane etc. sein.


----------



## Marco13 (17. Mrz 2012)

L-ectron-X hat gesagt.:


> Das macht auch Sinn. Zu viele innere Klassen sollen sich recht unperformant auswirken.



[OT](Zumindest so halb: ) Inwiefern haben innere Klassen Einfluß auf die Performance?[/OT]


----------



## tfa (17. Mrz 2012)

Marco13 hat gesagt.:


> [OT](Zumindest so halb: ) Inwiefern haben innere Klassen Einfluß auf die Performance?[/OT]



Die inneren Objekte halten eine Referenz auf das äußere. Das ist erstmal ein kleiner Overhead. Außerdem steigt die Gefahr von Speicherlecks, was sicherlich schlimmer ist. Wer keine inner class braucht, kann ja genauso gut eine static nested class verwenden (Findbugs findet übrigens automatisch solche Kandidaten).


----------



## Marco13 (17. Mrz 2012)

OK, ich bin bei "innere Klasse" jetzt davon ausgegangen, dass es in erster Linie um statische geht. Nicht-statische können IMHO (nicht pauschal, aber in manchen Fällen) etwas "unschöne" Strukturen hervorbringen...


----------



## maki (17. Mrz 2012)

Bei nicht-statischen innere Klassen gibt es pro Instanz der äusseren Klassen (also Objekt der äusseren Klasse) eine eigene innere Klasse.


----------



## tfa (17. Mrz 2012)

> OK, ich bin bei "innere Klasse" jetzt davon ausgegangen, dass es in erster Linie um statische geht.


Sry, wenn ich "innere Klasse" lese denke ich immer an _inner classes_, und die gibt's nur in nicht-statisch.


----------



## Marco13 (18. Mrz 2012)

Jaja, war eine falsche Verwendung der Begriffe meinerseits


----------

