Hallo zusammen, schön, dass es dieses Forum noch gibt 
Ich stehe vor folgender Problemstellung: Aus Nachrichten, die über eine beliebige Schnittstelle (Netzwerk, Dateien, ...) empfangen werden, soll jeweils ein entsprechendes Nachrichten-Objekt instanziiert werden. Der Aufbau aller möglichen Nachrichten ist genau gleich (Kopf, Inhalt, Fuß), die Datentypen der Inhalte sind jedoch unterschiedlich und stehen in keinerlei Zusammenhang. Eine Büchernachricht enthält beispielsweise eine Liste von Büchern, während eine Benutzernachricht den Namen und das aktuelle Kartenguthaben enthält. Der Inhalt der Nachricht lässt sich also nicht in einem Datentyp zusammenfassen, somit kann ich für die abstrakte Klasse oder das Interface auch keinen Rückgabewert für eine 'getInhalt()' Methode angeben.
Zusätzlich soll die Art und Weise, wie der Inhalt der Nachricht geparst und die entsprechenden Objekte instanziiert werden, innerhalb der von Nachricht abgeleiteten Basisklasse befinden, damit man beim Empfangen einfach
Code:
Nachricht nachricht = NachrichtenParser.Parse(nachrichtenString);
aufrufen kann. Je nach Nachrichtentyp möchte ich dann bei der Weiterverarbeitung die Liste von Büchern oder das Guthaben ausgeben.
Code:
Nachricht nachricht = NachrichtenParser.Parse(nachrichtenString);
List<Buch> buecher = nachricht.getBuecher();
double guthaben = nachricht.getGuthaben();
if(buecher == null)
...
Die beiden Methoden 'getBuecher()' und 'getGuthaben()' haben in der Basisklasse Nachricht jedoch meiner Meinung nach nichts zu suchen, wenn beispielsweise 100 Nachrichtentypen existieren müsste man ja 100 Funktionen haben, von denen nur eine einzige gebraucht wird (Deshalb würde ich auch das Visitor-Pattern ausschließen).
Einfacher wäre es mit Downcasting
Code:
Nachricht nachricht = NachrichtenParser.Parse(nachrichtenString);
if(nachricht is Buechernachricht)
List<Buch> buecher = ((Buechernachricht)nachricht).getBuecher();
...
Das ist aber wiederum sehr sehr unflexibel und widerspricht dem Open-Closed-Prinzip.
Ich habe auch bereits mit dem Decorator-Pattern experimentiert
Code:
Nachricht nachricht = NachrichtenParser.Parse(nachrichtenString);
BuecherNachrichtDecorator buchnachricht = new BuecherNachrichtDecorator(nachricht);
List<Buch> buecher = buchnachricht.getBuecher();
und in der Decorator-Klasse entsprechend
Code:
class BuecherNachrichtDecorator : Nachricht
{
private Nachricht nachricht;
public BuecherNachrichtDecorator(Nachricht msg)
{
nachricht = msg;
}
public List<Buch> getBuecher()
{
if(nachricht is BuecherNachricht)
BuchNachrichtContentParser contentParser = new BuchNachrichtContentParser();
return contentParser.Parse(msg.getContentAsString());
}
}
Die Klasse Nachricht ist in diesem Kontext keine Basisklasse mehr und parst den Nachrichtenstring in Kopf, Inhalt und Fuß. Ein ContentParser wandelt dann den string in eine Liste von Büchern um. Man sieht jedoch, dass es prinzipiell das selbe nur in eine andere Klasse geschoben ist (Wieder wird über RTTI der Typ abgefragt). Sollte ich vielleicht nur den ContentParser aufrufen und wenn er den Inhalt nicht parsen kann null zurückgeben? Dann müsste ich jedoch alle vorhandenen Parser durchprobieren, bis einer was zurückgibt.
Ich stehe hier auf dem Schlauch, daher meine Frage:
Ich habe eine Klasse Nachricht, deren Inhalt 100 verschiedene Datentypen annehmen kann. Wie kann ich, ohne Reflection oder RTTI, möglichst elegant und entkoppelt ein Nachricht-Objekt aufgrund eines Strings erstellen und im Nachhinein den Inhalt der Nachricht im passenden Datentyp abfragen.
Viele Grüße,
Delta