Patterns für schöneren Code bei vielen instanceof Abfragen



  • Hallo,

    folgendes Problem:
    Ich habe von xjc generierte Java-Klassen, die den Inhalt einer XML speichern.
    Nun muss ich diese generierten Klassen in einem entsprechenden Converter umwandeln in tatsächliche Domain-Klassen, also z.B. ProductType (von xjc generiertes POJO) in Product (meine Domain Klasse).
    Dazu lese ich natürlich die Daten der ProductType-Instanz, die durch das Mappen von XML -> POJO entstanden sind, und setzte die entsprechenden Felder von meiner Product-Instanz. Dabei kommt öfter auch gewisse Logik zum Einsatz.

    Das Problem hierbei ist, dass ProductType und alle anderen XML-Types ganz oft solche List<Object> Konstrukte haben. Object kann dann tatsächlich zick verschiedenen Klassen sein, die meisten davon auch relevant.
    Im Code meines Convertes habe ich dann also etliche for-Schleifen mit etlichen if-else Verzweigungen, in denen ich jeweils mit instanceof prüfen muss, um was es sich da eigentlich gerade handelt und dann entsprechend darauf reagieren muss.
    Das wirkt auch mich irgendwie sehr unschön und da stelle ich mir die Frage, ob man da als guter Java-Entwickler ein Pattern anwendet?

    Etwas Recherche bringt das Visitor-Pattern auf den Tisch, allerdings habe ich dazu auch direkt viel Kritik gelesen. Das wäre dann doch auch nur boilerplate code der auch nichts verbessert.

    Was meint denn Ihr dazu? Würdet ihr ein Design-Pattern anwenden und wenn ja welches und warum?

    Danke!



  • Ich kann das ganze auch nicht über eine Map verschönern, da ja keine Polymorphie gegeben ist, oder?

    Schön wäre halt eine Map, deren Key sozusagen der object.getClass() wäre und deren value dann der entsprechende Converter für diesen Typen.

    Verwenden würde man den dann so

    // toProcess ist vom Typ Object
    map.get(toProcess.getClass()).process(toProcess);
    

    process müsste ja dann aber in der Baseklasse dieser Converter die Signatur void process(Object target) haben. In der Subklasse müsste sie aber die konkreten Fälle annehmen, also z.B. void process(ValueType target) was dann aber kein override wäre, da ValueType nicht von Object erbt.

    Hm, nun ja ich könnte in den Unterklassen auch Object nehmen und dann halt entsprechend casten, korrekt?
    Dann würde ich meine Map einmal etwa so initialisieren

    map.put(ValueType.class, new ValueTypeConverter());
    map.put(NameType.class, new NameTypeConverter());
    ...
    

    Und dann könnte ich es wie oben beschrieben callen.

    Ist das jetzt besser? Keine Ahnung ehrlich gesagt.
    Ich spare mir if-else Verzweigungen aber muss dafür 8-9 neue Klassen anlegen.


Log in to reply