2016-04-19 11 views
0

Ich habe folgende sehr einfache Schnittstelle:Wie man einfach eine Fabrik von mehreren Parameter-divergierenden Klassen mit Guice handhabt?

public interface IDataSource<T> { 
    Observable<T> observable(); 
} 

Jetzt werde ich es mehrere Implementierungen werden müssen. Jede dieser Implementierungen kann sich auf unterschiedliche Parameter stützen (verschiedene Speicherobjekte: JDBC, Cassandra, Redis ...). Also zum Beispiel werde ich haben:

public class CassandraDataSource implements IDataSource<MyCassandraObject> { 
    @Inject 
    public CassandraDataSource(Keyspace ks) { 
     // ... 
    } 
} 

public class OtherCassandraDataSource implements IDataSource<MyOtherCassandraObject> { 
    @Inject 
    public OtherCassandraDataSource(Keyspace ks) { 
     // ... 
    } 
} 

public class JDBCDataSource implements IDataSource<MyJdbcObject> { 
    @Inject 
    public JDBCDataSource(Database db) { 
     // ... 
    } 
} 

Und so weiter.

Was ich möchte, ist jeder der mit einer Zeichenfolge zu verweisen, so dass ich eine Fabrik aufrufen kann, die die entsprechende IDataSource zurückgeben würde. Etwas, das sich so verhalten würde:

public class DataSourceFactory { 
    public static final Map<String, Supplier<IDataSource<?>>> map = new HashMap<>(); 

    @SuppressWarnings("unchecked") 
    public <T> IDataSource<T> get(String ref) { 
     return (IDataSource<T>) map.get(ref).get(); 
    } 
} 

ich geben könnte N Providers als Parameter (oder direkte Feld Injektion) zu meiner Fabrik und Karte Strings, die den in den Konstruktor (N die Anzahl der IDataSource Ich benutze ist) oder Verwenden Sie einen Schalter in der get Methode, aber das würde ziemlich ein Chaos werden, sobald ich 10 bis 20 erreichen IDataSource (oder mehr!)

Gibt es eine einfachere Lösung, die ich übersehen habe?

Dank

Antwort

0

Wenn Sie eine Fabrik haben, dann no- as in this question ein manuelles Werk ist wahrscheinlich das Beste, was Sie bekommen können.

Wenn Sie jedoch alle Ihre IDataSource-Implementierungen an IDataSource mit unterschiedlichen Bindungsanmerkungen binden, können Sie möglicherweise die Factory überspringen und einfach @Source("foo") IDataSource injizieren und die gewünschte Instanz zurückerhalten. Die Konfiguration zwischen String und Implementierung muss noch irgendwo existieren, aber Sie können sie in einem Guice-Modul leben lassen, wenn Sie möchten. Und indem Sie den Injektor injizieren und eine kompatible Annotationsimplementierung bereitstellen, können Sie sogar eine Factory wie DataSourceFactory schreiben, die auf Guice verweist.

Als eine Randnotiz, hüten Sie sich vor Ihrer DataSourceFactory; get hat keine sichere Möglichkeit, einen Wert für seinen Typparameter T zu liefern.