Zusammenspiel Oberfläche mit OOP gedanken
-
Hallo Ihr,
ich habe mal eine allgemeine Frage zur Integration eine Oberfläche in OOP Code (Java und C# aber das Problem ist Sprachen unabhängig).
Ich versuche mal zu schildern was mein Problem ist.
Die Logig meines Programms steht und ich finde es auch nach dem OOP Gedanken gut gelöst. Jetzt wollte ich eine Oberfläche dazuführen. Und damit fangen die Probleme an. Zur Zeit waren alle Ausgaben für die Command-Line geschrieben.
In der Anwendung gab es Anweisungen wie Console.WriteLine("test");
Jetzt soll diese Meldung in ein Controll im Fenster ausgegenen werden.
Jetzt könnte ich in meinen Programm das einfügen, aber damit ist die Klasse nur noch mit meinem Fenster zu gebrauchen und nicht mehr allgemein.Wie kann ich den Code erstellen damit ich sowohl die Klasse mit Oberfläche benutzen kann als auch Problemlos weitergeben kann und z.B. mit Comandline Ausgabe betreiben kann oder vielleicht ganz ohne Ausgabe.
Ich denke, das sollte mit einer Interface Klasse gehen oder???
Ich weiss leider nur nicht wie..
Vielleicht kann mir jemand helfen Klarheit zu bekommen.Ich hoffe, ich habe mich klar ausgedrückt.
Pedro
-
schreib einfach eine globale funktion für die terminalausgabe
wohin die ausgabe wandert entscheidet die funktion intern
-
@Sovok: Das mit der globalen funktion verstehe ich nicht, was du damit meinst.
Noch etwas: Es geht um Trennung zwischen Modell und View.
Hat jemand ein eine Idee wie das geht?Pedro
-
Meine Herangehensweise wäre da eine abstrakte Klasse oder ein Interface, das die Ausgabe repräsentiert. Nennen wir diese Klasse mal AbstractView. Für dein Beispiel würde diese Klasse jetzt eine abstrakte Methode "printMessage" oder so deklarieren. Von der Klasse wird dann eine Klasse für die Arbeit mit der Konsole und eine für die Arbeit mit einer GUI abgeleitet und entsprechend wird jeweils die printMessage-Methode gestaltet.
In dem Programmteil, der sich mit der Programmlogik beschäftigt, wird dann nur mit der abstrakten Klasse AbstractView gearbeitet. Du kannst da dann Polymorphie nutzen und je nach bedarf ein Objekt der Konsolen-Klasse oder der GUI-Klasse durch die AbstractView-Variable referenzieren. So kannst du dann einfach irgendwo mit einem Schalter zwischen GUI und Konsole umschalten.
-
halt ich für viel zu umständlich für sowas simples
mit globaler funktion mein ich
void Print ( const char* sMsg ) { if ( g_hFenster != NULL ) { g_hFenster->Print ( sMsg ); // g_hFenster = globales handle auf das fenster } else { cout << sMsg << endl; } }
-
@Gregor: Im Modell würde ich dann Interface.printMessage aufrufen, aber wie erfährt die View(GUI) das sie was tun muss?
Und wie geht es mit dem umgekehrten weg. Die View übermittelt daten an das Modell. Ruft sie Direkt die Modell Funktionen auf oder geht das auch über eine zwischen Schicht?
Danke!
Pedro
-
Hallo,
im Prinzip ist Gregors Ansatz schonmal korrekt. So kann die Ausgabe auf eine beliebige Art erfolgen.
Bei größeren Sachen ist aber wie Du schon sagst aus meiner Sicht eine weitere "Schicht" nötig, meist Controller genannt. Dieser wird über jede Änderung (z.B. von Eingabewerten) von der View aufgerufen, ändert die Dtaen des Modells und benachrichtigt die GUI, sich "upzudaten". Denn normalerweise gehören in die Datenhaltung keine Aufrufe wie printMessage().
-
Cosmixx schrieb:
Bei größeren Sachen ist aber wie Du schon sagst aus meiner Sicht eine weitere "Schicht" nötig, meist Controller genannt. Dieser wird über jede Änderung (z.B. von Eingabewerten) von der View aufgerufen, ändert die Dtaen des Modells und benachrichtigt die GUI, sich "upzudaten". Denn normalerweise gehören in die Datenhaltung keine Aufrufe wie printMessage().
Ja, natürlich. Ich bin bei meinem Beitrag nicht von einem "Model-View" Konzept ausgegangen, sondern von einem "Model-View-Controller"-Konzept. Die printMessage-Methode befände sich da im View-Teil und würde vom Controller aufgerufen werden. Den Controller habe ich da oben einfach mal als "Programmlogik-Teil" beschrieben. Das "Model" spielt da soweit noch gar keine Rolle. Das ist "auf der anderen Seite" mit dem Controller verbunden.
-
Pedro_15 schrieb:
Und wie geht es mit dem umgekehrten weg. Die View übermittelt daten an das Modell. Ruft sie Direkt die Modell Funktionen auf oder geht das auch über eine zwischen Schicht?
Auch das würde über den Controller ablaufen.
-
Sovok schrieb:
halt ich für viel zu umständlich für sowas simples
mit globaler funktion mein ich
void Print ( const char* sMsg ) { if ( g_hFenster != NULL ) { g_hFenster->Print ( sMsg ); // g_hFenster = globales handle auf das fenster } else { cout << sMsg << endl; } }
Sovok: Das führt zu unwartbarem Code, weil du die Funktionalitäten vermischt. Von dieser Herangehensweise rate ich definitiv ab. Wenn du an dem Verhalten der GUI etwas ändern willst, dann ist es äußerst schlecht, wenn du andauernd mit Konsolen-Code konfrontiert wirst.
-
Gregor schrieb:
Wenn du an dem Verhalten der GUI etwas ändern willst, dann ist es äußerst schlecht, wenn du andauernd mit Konsolen-Code konfrontiert wirst.
inwiefern "andauernd"
ich seh die funktion als global
d.h. sie könnte auch in einer bibliothek steckendem aufrufenden ist es egal wie die ausgabe intern gelöst ist, er will einfach nur die ausgaben anzeigen
sinnvoll wäre das z.b. damit auch ausgaben gemacht werden können bevor das fenster erzeugt und nachdem es gelöscht wurde
-
Sovok schrieb:
Gregor schrieb:
Wenn du an dem Verhalten der GUI etwas ändern willst, dann ist es äußerst schlecht, wenn du andauernd mit Konsolen-Code konfrontiert wirst.
inwiefern "andauernd"
ich seh die funktion als global
d.h. sie könnte auch in einer bibliothek steckendem aufrufenden ist es egal wie die ausgabe intern gelöst ist, er will einfach nur die ausgaben anzeigen
sinnvoll wäre das z.b. damit auch ausgaben gemacht werden können bevor das fenster erzeugt und nachdem es gelöscht wurde
Eine GUI hat i.d.R. mehr als ein Fenster, also bräuchte man dann entsprechend viele
Funktionen, zu dem bei dir noch hinzu kommt, das die Consolenversion GUI Variablen
hat, diese aber nicht braucht. Da macht es schon sinn, einen Controller dazwischen
zu schalten, der dann über ein Interface die GUI / Console steuert.
-
bin davon ausgegangen, dass es nur um die textausgabe ging
klar falls es mehrere features sind die geswitcht werden sollen ist die lösung mit der basisklasse sinnvoller aber bei kleinen einzelaufgaben wirkt zuviel oop eher unübersichtlich
-
-Sovok- schrieb:
bin davon ausgegangen, dass es nur um die textausgabe ging
klar falls es mehrere features sind die geswitcht werden sollen ist die lösung mit der basisklasse sinnvoller aber bei kleinen einzelaufgaben wirkt zuviel oop eher unübersichtlichDann war das wohl ein Missverständnis. Ich gehe bei solchen Fragen immer davon aus, dass nach einer allgemeinen Herangehensweise gefragt wird, die man auch bei größeren Projekten durchführen kann. Ein Beispiel, das irgendwo in der Fragestellung gebracht wird, wird meistens nicht die wirkliche Komplexität des eigentlichen Problems wiederspiegeln.
-
Heutzutage programmiert man keine GUI mehr im Code, sondern man erstellt seinen Code, bastelt sich eine GUI in einem GUI Editor und erzeugt dann Datenbindungen zwischen der GUI und dem Code.
Schau dir zB Adobes Adam & Eve oder Mozillas XUL & XBL an.
So trennt man Layout und Inhalt.
-
Hallo Ihr,
vielen Dank für die schnellen Antworten.
Habt Ihr für mich ein kleines Beispiel Projet wo man das mit dem Modell, View und dem Controller sehen kann?
Ein Tutorial über diese Thema würde mir auch weiter helfen.
Ich brauche einfach einen Startpunkt, noch ist bei mir alles unklar was wo und wie Implementiert wird und wie die Kommunikation erfolgt.
Vielen Dank für die hilfe!
Pedro