Factory Pattern: Mit Generics umgehen

Hi,

ich habe ein Interface Converter<I, S>, von dem es mehrere Implementierungen verschiedener Kategorien gibt.
Zur Laufzeit sollen die Converter austauschbar sein, weshalb ich mich für das Factory-Pattern entschieden habe. Problem hierbei sind die Generics.. Jede Implementierung hat für I und S komplett verschiedene Objekttypen. Kann ich nun trotzdem eine Factory erstellen, die mir ein Converter-Objekt zurück gibt, das nicht mehr gecastet werden muss?

Mein Interface sieht so aus

Code:
public interface Converter<I, S> {

    S convert(I i) throws Exception;
    boolean wasSuccessful();
   
}
Eine mögliche Implementierung sieht so aus

Code:
public class IntConverter implements Converter<String, List<Integer>>{

    @Override
    public List<Integer> convert(String s) {
        /**
         * do some conversions
         */
    }
}
oder

Code:
public class GradeConverter implements Convert<List<URL>, List<Grade>>{

    @Override
    public List<Grade> convert(List<URL> urls){
        /**
         * do some work
         */
    }
}
Wie baue ich dann mein Factory so, dass es nach außen hin typsicher bleibt?

Meine Factory sieht so aus
Code:
public static Converter<?, ?> createConverter(Type t) throws NoSuchDetectorException {

        switch (t) {
        case CASE1:
            return new IntConverter();
        case CASE2:
            return new GradeConverter();
        default:
            throw new NoSuchDetectorException("No converter installed for framework: " + t.getVal());

        }
    }
Wirklich dynamisch bin ich damit ja nicht unbedingt unterwegs. Hat jemand eventuell einen Tipp für mich?
 
Was ist denn Type für ein Typ?


Eine (mMn unschöne) Lösung wäre, createConverter generisch zu machen, dann brauchst du zumindest außerhalb keine Casts:

Code:
public static <T,I> Converter<T, I> createConverter(Type t) {

        switch (t) {
            case CASE1:
                return (Converter<T, I>) new IntConverter();
            case CASE2:
                return (Converter<T, I>) new GradeConverter();
            default:
                return null;
        }
    }

Wirklich dynamisch bin ich damit ja nicht unbedingt unterwegs
Was meinst du in dem Fall mit dynamisch?
 
Type ist ein Enum.

Deine Lösung gefällt mir schon besser. Dann habe ich nur einen zentralen Ort zur Pflege und Wartung des Codes. Wenn du die Lösung als unschön empfindest, hat jemand noch eine schöne Lösung parat?

Was meinst du in dem Fall mit dynamisch?
Damit meine ich einfach das benötigte Casting außerhalb der Factory.
 
Type ist ein Enum.

Deine Lösung gefällt mir schon besser. Dann habe ich nur einen zentralen Ort zur Pflege und Wartung des Codes. Wenn du die Lösung als unschön empfindest, hat jemand noch eine schöne Lösung parat?
Ich persönlich würde auf die Factory verzichten und den Enum als Factory nutzen.
Enum und switch in Kombination ist eigentlich immer Unsinn ;)

Ansonsten ginge noch generische AbstractFactory, und pro Typ dann eine eigene - das Mapping Typ<->Factory zB über eine Map (wobei man da vermutlich wieder casten müsste, je nach Umsetzung)
 
Ich würde es vermutlich wie folgt machen:
Java:
public class Type<T,I> {
   
    public static final Type<String, List<Integer>> INT_CONVERTER = new Type<>(IntConverter::new);
    public static final Type<List<URL>, List<Grade>> GRADE_CONVERTER = new Type<>(GradeConverter::new);
   
    private Supplier<Converter<T, I>> factory;
   
    private Type(Supplier<Converter<T, I>> factory) {
        this.factory = factory;
    }
   
    public Converter<T, I> getInstance() {
        return factory.get();
    }
}
Ist quasi die Lösung von mrBrown, also ohne Factory-Klasse. Allerdings habe ich aus dem Enum eine normale Klasse gemacht, die ein Enum nachahmt. Leider gibt es in Java keine generischen Enums.

Grüße
Kevin
 
Ok, die Idee dahinter verstehe ich. So muss ich bei Änderungen bzw. Erweiterungen lediglich ein neues Attribut anlegen, statt einen neuen Enum Case. Wie verhält es sich, wenn die Objekterstellung von mehreren Enums bzw. jetzt Klassen abhängt? Eine Map von Maps anlegen oder lieber eine eigene "Kriterienklasse" schreiben, die beinhaltet, welche Voraussetzungen zum Erstellen einer Klasse gelten?
 
Passende Stellenanzeigen aus deiner Region:

Neue Themen

Oben