PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Softwarearchitektur: Spezifische GUIs


ethrandil
2008-10-28, 19:18:05
Hallo,

ich habe ein Programm, in dem gibt es ein Interface A (sagen wir Apfel). Davon gibt es verschiedene Implementierungsklassen, beispielsweise ElstarApfel, BraeburnApfel, ...

Das Gui zeigt Informationen und Regler an, mit denen ein Apfel betrachtet und verändert werden kann. Allerdings gibt es einige der Äpfel, die noch zusätzliche Parameter haben. Wird ein solcher Apfel betrachtet, müssen andere Regler angezeigt werden.

Wie Löse ich das auf eine elegante Art und Weise, also möglichst ohne viele instanceofs und ohne dass die Äpfel dafür angepasst weden müssen?

(ist in Java, aber das sollte ja für die Achitektur egal sein)

- eth

Bietchiebatchie
2008-10-28, 19:45:47
Das Gui zeigt Informationen und Regler an, mit denen ein Apfel betrachtet und verändert werden kann. Allerdings gibt es einige der Äpfel, die noch zusätzliche Parameter haben. Wird ein solcher Apfel betrachtet, müssen andere Regler angezeigt werden.

Ich würde einfach die Gesamtmenge aller Parameter in die GUI packen und eben nur die Parameter (in der GUI) aktivieren die für den aktuellen Apfel relevant sind.


Wie Löse ich das auf eine elegante Art und Weise, also möglichst ohne viele instanceofs und ohne dass die Äpfel dafür angepasst weden müssen?

Wenn die Anzahl der Äpfelarten < 10 ist, würde ich vorschlagen: was spricht gegen instance-of? Sieht wahrscheinlich häßlich aus, ist aber definitiv der schnellste Weg - alles andere bläht nur deinen Code unnötig auf.

ethrandil
2008-10-28, 19:59:34
Ich würde einfach die Gesamtmenge aller Parameter in die GUI packen und eben nur die Parameter (in der GUI) aktivieren die für den aktuellen Apfel relevant sind.Prinzipiell gute Idee.

Wenn die Anzahl der Äpfelarten < 10 ist, würde ich vorschlagen: was spricht gegen instance-of? Sieht wahrscheinlich häßlich aus, ist aber definitiv der schnellste Weg - alles andere bläht nur deinen Code unnötig auf.
Es wird eine Bachelorarbeit und sie wird von einem Softwaretechniker korrigiert. Ich habe also den Anspruch eine ansprechende Architektur zu entwerfen, die auch bei großen Systemen noch angemessen ist.
Außerdem spricht noch dagegen, dass ich die Apfelanzahl steigere, es werden mehr als 10 und ich bin froh, wenn mir das auch später noch wenig Arbeit macht. Dafür würde ich auch den Code mit ein paar Architekturmustern 'aufblähen' ;-)

Shink
2008-10-28, 20:04:42
Wenn die Anzahl der Äpfelarten < 10 ist, würde ich vorschlagen: was spricht gegen instance-of? Sieht wahrscheinlich häßlich aus, ist aber definitiv der schnellste Weg - alles andere bläht nur deinen Code unnötig auf.
Bööööse!:eek:

Wie wäre es damit:
Jede Apfel-Klasse hat eine Factory-Methode createApfelGUI(). Vielleicht gibt es einen abstrakten DefaultApfel, da könnte man eine Defaultimplementierung reingeben (return new DefaultApfelGUI(this)) und manche Apfel-Klassen haben ihre eigene Implementierung und geben eine andere GUI zurück.

Schöner (wegen Trennung Model-View und Verzicht auf unnötige Vererbung wegen DefaultGUI) wäre eine eigene Factoryklasse die für einen Apfel eine GUI erstellt.

ethrandil
2008-10-28, 20:13:35
Wie wäre es damit:
Jede Apfel-Klasse hat eine Factory-Methode createApfelGUI(). Vielleicht gibt es einen abstrakten DefaultApfel, da könnte man eine Defaultimplementierung reingeben (return new DefaultApfelGUI(this)) und manche Apfel-Klassen haben ihre eigene Implementierung und geben eine andere GUI zurück.Das fällt durch den standardtest: "Sollte ein (abstrakter) Apfel sein GUI kennen? Neeein..."

Schöner (wegen Trennung Model-View und Verzicht auf unnötige Vererbung wegen DefaultGUI) wäre eine eigene Factoryklasse die für einen Apfel eine GUI erstellt.
Ja, an sowas habe ich auch mal gedacht. Aber dann hätte man das instanceof in der Factory-Klasse, oder? Oder gibt es pro Apfelklasse eine Factory? Und wie handelt man das bei letzterem, dass das GUI genau die eine Factoryklasse aufruft, die für den konkreten Apfel zuständig ist?

Trap
2008-10-28, 20:15:44
Du musst irgendwie auf den tatsächlichen Typ der Objekte zugreifen:
a) double dispatch/multi dispatch Erweiterung für Java
b) Visitor-Pattern (dafür muss man die Äpfel natürlich verändern)
c) instanceof/reflection
d) passende Wrapper mit erzeugen, solang du den konkreten Typ noch kennst

Shink
2008-10-28, 20:55:58
Aber dann hätte man das instanceof in der Factory-Klasse, oder? Oder gibt es pro Apfelklasse eine Factory?
Man könnte z.B. eine Map<Class<Apfel>, Class<ApfelGUI>> verwenden.
Da kommt dann z.B. (ElsterApfel.class, ElsterApfelGUI.class) rein.

Bei createApfelGUI(Apfel a) wird dann geschaut ob a.getClass() in der Map drin ist. Wenn ja, eine newInstance() der GUI-Klasse erstellen, sonst eine DefaultApfelGUI.

Alternativ, braver und portabler: In die Map zur Apfel-Klasse eine Instanz einer ApfelGUIFactory rein. (Dann gibt es tatsächlich für jede ApfelGUI eine eigene Factory)

Böse aber bei großen Massen sehr praktisch: Mit Class.forName() schauen ob es apfelInstanz.getClass().getName()+"GUI" gibt.

Visitor-Pattern ist denke ich nicht sehr praktisch hier.

Achill
2008-10-28, 23:17:04
Hallo ethrandil

Hier kurz ein paar Gedanken (weiß nicht ob es zu später Stunde noch etwas taugen):

1. Zerlegung der Eigenschaften in einzelne Interfaces mit setX oder getX (wenn Menge aller Parameter bekannt, sonst weg lassen).

2. Eine Art Interpreter zum Erzeugen der Menge aller Eigenschaften + Gekapselter Zugriff verwenden (Parameter bekannt, dann Interfaces oder auch gleich Zugriffs-Objekt(e) die den Bezeichner & je nach dem get / set unterstützen und an den Apfel weiter delegieren - diese könnten auch das Feuern von (Änderungs-)Events für die GUI mit abdecken und könnten ein entsprechenden Model umsetzen, ohne dass die konkrete Ausprägung des Apfel geändert werden musst).

3. Ein Builder, der auf Basis deiner Eigenschaftsmenge die GUI aufzubaut. Die GUI-Komponenten könnten dann beliebig klein (Slider für Größe, Palette für die erste Farbe, ...) und maximal wieder verwendet werden. Über Regeln könnten sich Komponenten der GUI gegenseitig ein und ausblenden (Rule-Engine?) oder die zu wählende Render-Komponente definieren.

Die Teile der GUI sind voneinander unabhängig, z.B. die Änderung des Sliders für die Größe würde nur das Zugriffs-Objekt für diesen Parameter kennen (und komplexere nur die nötigsten), dies reicht den Wert an dein Apfel weiter und feuert anschließen ein Event auf das andere Komponenten reagieren können.

Hoffe das ist jetzt zu sehr durcheinander ... ist schon spät ;)

Shink
2008-10-29, 10:46:59
Hier kurz ein paar Gedanken (weiß nicht ob es zu später Stunde noch etwas taugen):
Ja, das sieht mir nach einer sinnvollen Ausarbeitung des Themas mit Patterns aus.

Gast
2008-10-29, 14:28:17
Man kann doch für den Basisapfel eine Basis UI erstellen und die anderen UIs erben dann einfach von dieser und erweitern diese jeweils um eigene Elemente. Danach kann man das ganze doch per Reflection laden.

ethrandil
2008-10-29, 16:27:42
Man kann doch für den Basisapfel eine Basis UI erstellen und die anderen UIs erben dann einfach von dieser und erweitern diese jeweils um eigene Elemente.
2x Ja
Danach kann man das ganze doch per Reflection laden.
1x Ja, Aber:
Das will man eigentlich nicht. Reflection ist ein Bad Smell und nicht zu unrecht.

Ich nehm mal Stellung zu den anderen Punkten, wenn ich wieder zuhause bin.

Gast
2008-10-29, 17:03:33
Reflection ist ein Bad Smell und nicht zu unrecht.


Naja, aber wenn es richtig flexibel sein soll, sehe ich keine Alternative.
Das Problem könnte ja höchstens sein, dass du einen Typen im String angibst, den es nicht gibt. Aber dafür kann man ja wenigstens zuvor einen Check machen und ggf. die Exception abfangen.

ethrandil
2008-10-30, 02:42:29
1. Zerlegung der Eigenschaften in einzelne Interfaces mit setX oder getX (wenn Menge aller Parameter bekannt, sonst weg lassen).

2. Eine Art Interpreter zum Erzeugen der Menge aller Eigenschaften + Gekapselter Zugriff verwenden (Parameter bekannt, dann Interfaces oder auch gleich Zugriffs-Objekt(e) die den Bezeichner & je nach dem get / set unterstützen und an den Apfel weiter delegieren - diese könnten auch das Feuern von (Änderungs-)Events für die GUI mit abdecken und könnten ein entsprechenden Model umsetzen, ohne dass die konkrete Ausprägung des Apfel geändert werden musst).

3. Ein Builder, der auf Basis deiner Eigenschaftsmenge die GUI aufzubaut. Die GUI-Komponenten könnten dann beliebig klein (Slider für Größe, Palette für die erste Farbe, ...) und maximal wieder verwendet werden. Über Regeln könnten sich Komponenten der GUI gegenseitig ein und ausblenden (Rule-Engine?) oder die zu wählende Render-Komponente definieren.
Also das klingt mir dann doch eine Spur zu groß, aber ich finde die Idee großartig für solche Fälle, in denen das custom-GUI sehr vielfältig ist, oder sogar dynamisch erzeugt werden muss :-D.

Ich weiß noch nicht, was ich tatsächlich umsetzen werde... aber evtl. läuft es doch auf a) eine klitzekleine Änderung der Apfel-Schnittstelle oder ein paar klitzekleine instanceofs heraus :rolleyes:

Danke an alle, die hier vorschläge gemacht haben und zu 'maximale flexibilität = reflection': Ja, aber nicht maximale Verständlichkeit, Änderbarkeit, Testbarkeit ;)

Gast
2008-11-19, 17:49:05
Ist schon etwas Älter, aber ich bin über den Thread gestolpert.

Was spricht gegen eine Abstract Factory Pattern.

Du hast also ein Interface AbstractFactory mit den Methoden CreateApple() und CreateAppleGUI(), die nach außen Sichtbar nur die abstrakten Basisklassen zurückgeben, intern aber die Konkreten Objekte erzeugen.

Für jeden Apfel muss es dann eine solche Abstrakte Fabrik geben.

Siehe http://de.wikipedia.org/wiki/Abstrakte_Fabrik