Swing Gui von Anwendungslogik trennen

wolfgang63

Bekanntes Mitglied
Hallo zusammen,
ich arbeite gerade an einem Programm bei dem ich die Benutzerschnittstelle über ein Interface von der Programmlogik trennen möchte, damit man später problemlos die Benuttzeroberfläche ändern kann. Was ein Interface ist und wie man es programmiert ist mir klar.
Was mir noch nicht klar ist, wer implementiert in meinem Fall das Interface?
Die Gui oder das Mainprogramm?
Geht das überhaubt, dass die Kontrolle die Mainklasse hat, denn im Grunde macht ja das Programm was der Benutzer über die Gui auslöst.
Weis jemand ein einfaches Beispiel solch einer Trennung via Schnittstelle? ???:L
 

wolfgang63

Bekanntes Mitglied
Hallo,
die GUI in eine eigene Klasse zu schreiben mache ich sowieso. Das Problem ist, die Kommunikation zwischen Logik und Gui ist dann so voneinander Abhängig das man die Gui nicht ohne weiteres austauschen kann.
Wenn man gegen eine Schnittstelle programmiert ist diese genau definiert und man kann die Guiklassen austauschen ohne die Logik an zu fassen. Soweit die Theorie. Praxis ???
 

Gucky

Top Contributor
Ach so meinst du das. Dazu bräuchtest du ein Interface Steuerable (Name änderbar), dass setter und getter bereitstellt, sowie die Methode machLogik. Dieses Interface wird von beiden Klassen implementiert. Dann baust du die GUI und die Logik um dieses Interface herum auf.
MachLogik wird von irgendwas aufgerufen (Thread, Button etc.) und ruft in der Logikklasse machLogik auf, die dann in der Logikklasse schalten und walten kann.
 

Gucky

Top Contributor
Genau. Schließlich hast du sie im Interface angegeben.

Du kannst auch zwei Interfaces machen. Das würde ein bisschen Aufgeräumter wirken. Du brauchst keine Getter in der GUI Klasse.
 

ChristianK

Aktives Mitglied
Wie macht man dann die konkreten Logik-Klassen den konkreten GUI-Klassen bekannt und umgekehrt? Über eine Factory (also Class.*) o.ä.?

Es geht mir speziell darum, die Komponenten so lose wie nur möglich zu haben. Ich möchte ohne neues Kompilieren eine GUI austauschen können.
 

Gucky

Top Contributor
In der GUI: Logikklasse log = new Logikklasse()

Ohne Compilieren wird eng, da du zumindest die GUI compilieren musst. Aber eigentlich müssten alle Attribute aus der GUI irgendwie in die Logik geschafft werden. Das ginge nur über setter und getter, den Konstruktor oder das Übergeben der Instanz der GUI Klasse, was ich aber für schlechten Stil halte.

Das, was du vor hast, ist gerade das, was die OOP will. Einzelne Module schaffen, die wiederverwendbar sind. Wenn du die Logik einmal richtig gebaut hast, dann musst du die GUI nur darum herum aufbauen und nicht andersrum.

Aber warum in diesem Thread und nicht in einem eigenen?
 

ChristianK

Aktives Mitglied
Ich dachte, es wäre keine komplett neue Frage sondern passe sehr gut in den Kontext dieses Themas, deshalb auch kein neues.

Ich komme eben eher aus dem PHP/Web-Bereich, da sind einige Dinge etwas anders. Dynamisches Laden von Klassen gestaltet sich für mich (gerade in PHP) etwas durchsichtiger als in Java.

Die Grundidee hinter dieser Frage ist eine App, die ein Socket Server/Client darstellt. Es soll ein Befehlsregister geben, möglichst unabhängig des eigentlichen Socket-Handlings und losgekoppelt von der Logik. Später soll (speziell für den Client) eine GUI drunherum gebaut werden.

Ziel soll es ja sein, den gleichen Code (gerade das Befehlsregister) mehrfach verwenden zu können. Das habe ich über Interfaces und eine Factory (der alle Befehle bekannt sind) gelöst. Leider weis ich nicht, ob ich damit auf einem guten Weg bin...
 

Gucky

Top Contributor
Das ist doch zu Offtopic. Da solltest du lieber einen neuen Thread zu erstellen. Dem Themenstarter ging es darum eine Logik und eine GUI zu machen und du bist schon fortgeschrittener und willst Klassen dynamisch nachladen. Und das in Apps mit Servern und so einem Kram. Dafür gibt es eigene Foren.

Und mir ist nicht so ganz klar, was du bezwecken möchtest. Willst du die Updates für deine App leichter gestalten? Oder ist dein Programm so groß, dass du einzelne Klassen nachladen willst?
 

wef34fewrg

Aktives Mitglied
Mich würd auch mal interessieren, wie das gemeint ist?!

Also an irgendeinem Zeitpunkt wirst du die GUI ja kompilieren. Die Frage ist nur, ob du das dem Client überlassen willst, der sich dann die passende GUI raussuchen soll, oder ob du die kompilierte Klasse auf dem Server haben willst, welcher dann die class Datei zum Client schickt, der sie dann benutzt und anzeigt?
 

ChristianK

Aktives Mitglied
Ok - für das nächste Mal merke ich mir das. Ist es für dieses ok, wenn wir hier bleiben? Ansonsten wird der Zusammenhang doch etwas schleierhaft (wenn man über 2 Themen wechseln muss)...

Es geht darum, dass ich ohne die komplette Anwendung neu kompilieren zu müssen einzelne Anwendungsteile austauschen kann. Also so, dass ich ein .jar-File einem Anwender sende und damit die GUI ein Update bekommt (oder das Befehlsregister, ...). Da diese einzelnen Komponenten auf Server- sowie Client-Ebene gleich sind ist es auch "einfacher" zu reproduzieren, welche Teilkomponente in welcher Version verwendet wird. Ansonsten ergibt sich ja beim Update einer Teilkomponente ein Update der ganzen Applikation (da neu kompiliert).
 

wef34fewrg

Aktives Mitglied
Ahoi hoi.

Dynamisches laden von Klassen ist in Java grundsätzlich möglich. Dazu schau dir mal
das, besonders das oder das an. Sind nur erste Anlaufstellen, die dir aber bestimmt helfen werden, da das Einbinden zwar mit Fehlerquellen verbunden ist, die Programmierlogik dahinter aber kein Hexenwerk beinhaltet. Reflection ist ein Stichwort, dass dich weiter bringen wird und im Stackoverflow Forum findest du einiges zum Thema "dynamically load jar at runtime".

Gibt einige Sachen, über die du dir den Kopf zerbrechen kannst. Hier wird
Java:
{
    Class classObject = Class.forName(pathToClassFile);
    MyClass myTestObject = (MyClass) classObject.newInstance();
}
eine Klasse zur Laufzeit geladen. Macht allerdings schon eher wenig Sinn, da beim casten (MyClass) die Klasse dennoch vorhanden sein muss, was du ja glaube ich nicht willst.
Das Problem kannst du beispielsweise umgehen, in dem jeder Client in seinem Code mit einem Interface arbeitet, welches alle Methoden enthält, mit denen die GUI arbeitet. Das jeweilige Objekt aus der geschickten class File, welches dann die GUI Klasse enthält, kannst du dann als Referenz(Interface) speichern (so hattest du das gemeint oder?).
Gänzlich ohne Interface würde es allerdings auch mit classObject.getMethod("methodName").invoke(argumentsList) funktionieren. Dazu schau dir unbedingt das an reflection

Wenn du von einer App sprichst, geh ich von Android aus. Dalvik nutzt da meines Wissens nach die DexClassLoader Klasse für das dynamische nachladen, damit hab ich jetzt allerdings noch keine Erfahrungen gemacht. Wird sich aber von dem bisherigen nicht gar so unterscheiden.

Dynamisches laden/binden solltest du in Java sparsam einsetzen. Wenn du fortlaufend nicht darauf verzichten willst, dann schau dir mal Projekte wie groovy an. Da kannst du dich dann als PHPler voll austoben.

Eine ganz andere Möglichkeit wäre es das Problem in Form von Serialisierung von Objekten in Verbindung mit TCP oder mit RMI zu lösen.
Es wäre möglich eine ViewGroup (app) bzw. eine Panel/AWT -JPanel/Swing) Klasse zu erstellen, welche eine vorgefertigte Oberfläche bietet. Bei Bedarf wird davon ein Objekt erstellt, welches serialisiert wird (also in einen Bytestrom geschrieben, welcher per TCP übertragen wird) und beim Client als GUI Objekte genutzt werden kann.
Stelle ich mir in AWT/SWING einfach vor, für Android allerdings schon ein wenig komplizierter.
 
Zuletzt bearbeitet:

ChristianK

Aktives Mitglied
Oha. Ich danke dir schon einmal vielmals für deinen Beitrag! Sehr ausführlich.

Ich dachte nicht ganz daran, dass komplette JAR erst zur Laufzeit zu laden, sondern es mit dem Programmstart über den Classpath zu integrieren. Da muss ich wohl überall gegen Interfaces programmieren, scheint mir der logischere Weg zu sein. Mit Reflection habe ich mich heute etwas ausgetobt - das birgt ab und an noch einige gefährliche Stellen, sieht aber auf jeden Fall sehr interessant aus.

Aus der PHP-Welt kenne ich eben Autoloading (gibt es ja so nicht direkt in Java) und Dependency Injection, wobei mir speziell letzteres in Java manchmal etwas schwer fällt. Das Abwägen, ob jetzt import & new oder ein DI besser ist...


Nicht ganz, ich spreche schon eher von Desktop-Programm; das hat sich irgendwie "eingebürgert", da auch App zu sagen - mein Fehler. Deine Idee mit dem TCP/RMI finde ich jedoch auch sehr interessant. Obwohl das dann vielleicht wieder mehr Nachteile bringen kann als es Vorteile bringt.
 

wef34fewrg

Aktives Mitglied
Nicht ganz, ich spreche schon eher von Desktop-Programm; das hat sich irgendwie "eingebürgert", da auch App zu sagen - mein Fehler. Deine Idee mit dem TCP/RMI finde ich jedoch auch sehr interessant. Obwohl das dann vielleicht wieder mehr Nachteile bringen kann als es Vorteile bringt.


Vielleicht kommt es darauf an, was du als Nachteil siehst?! Bei Apps (also "wirklichen" Apps ;)) würden mir spontan drei oder vier Dinge einfallen, die für Reflection sprechen würden. Nun, bei Desktopanwendungen fällt mir das vielleicht etwas schwerer, oder ich verstehe die Komplexität deines Vorhabens nicht. :oops:
 
Zuletzt bearbeitet:

turtle

Top Contributor
Ich möchte ohne neues Kompilieren eine GUI austauschen können.

Wow, das ist mal ein ambitioniertes Vorhaben, aber...

Meine Erfahrung ist eher umgekehrt. Nämlich man hat eine GUI und möchte den "Server"teil austauschen. Eigentlich sind die Verzahnungen zwischen GUI und Logik so eng, das ich mir nicht vorstellen kann, das eine GUI komplett getauscht werden kann.

Ich möchte dich ja nicht entmutigen, aber wenn das ziemlich einfach wäre, würde es davon mehr Anwendungen geben.

Die bisherigen Aussagen hier waren sicherlich richtig und hilfreich. Meine Konzeptfrage ist immer, wie eine GUI mit Validierungen umgehen soll. Nehmen wir an eine Eingabe des Geburtstages einer Person wird in der GUI gemacht. Diese Validierung sollte wohl der Logikteil machen. Aber sobald ich da etwas ändere, zum Beispiel nicht mehr drei getrennte Felder für Tag,Monat und Jahr sondern ein Control, das einen Kalender anzeigt, ist worst-case überhaupt keine Validierung mehr notwendig. Daher sind GUI/Logik IMMER eng verzahnt und man kann das Eine nicht leicht tauschen ohne das Andere anzupassen, schon gar nicht ohne neues Kompilieren.

Dies bedeutet nicht, das man sich keine Gedanken darum machen muss. Ein guter Ansatz ist die Umsetzung des MVC-Pattern, das eine weitreichende Entkoppelung der Schichten erlaubt.
 

ChristianK

Aktives Mitglied
Allzu komplex ist mein Vorhaben nicht. Im Endeffekt entsteht eine Anwendung, die Backups von definierten Verzeichnissen ausführt. Dabei werden die Dateien über SCP übertragen und Informationen zur Datei über einen Socket. Mein Ziel ist es, die Anwendung für Client- und Server-Seite nur einmal entwickeln zu müssen. Deshalb soll eine lose Koppelung zwischen den einzelnen Komponenten (Befehlsregister, Socket, Logik, GUI) bestehen, um diese Komponenten austauschbar zu machen.

Ich denke schon, dass die Reflection bei Desktop-Applikationen eher mehr Nach- als Vorteile bietet im Vergleich zu mobilen Apps. Dennoch möchte ich versuchen, dies möglichst "flexibel" zu gestalten.

@turtle: Jetzt auf deinen spezifischen Fall bezogen. Hier dürfte man sich wohl streiten... Die Validierung mag zwar Sache der Logik sein, jedoch kann die Logik eine Validierung (schematisch) mit Logical.validateInput() ausführen. Das Resultat dieser Validierung zu behandeln liegt dann wieder in der Obhand der GUI/"Front-Controller". Mit diesem Prinzip wären wir wohl sehr nahe an MVC... Da ich jedoch mit Desktop-Apps nicht sehr viel Erfahrung habe, stelle ich mir (berechtigt?) die Frage, ob MVC auch im Java-Desktop-Bereich konkret eine Möglichkeit ist?!
 

Ähnliche Java Themen

Neue Themen


Oben