Domanda

Mi riferisco al "prestatore di servizi quadro", come discusso in capitolo 2 del Effective Java , che sembra esattamente il modo giusto per gestire un problema che sto avendo, in cui ho bisogno di istanziare una delle diverse classi in fase di esecuzione, sulla base di un String per scegliere quale servizio, e un oggetto Configuration (essenzialmente un frammento di XML) :

Ma come faccio ad avere i singoli fornitori di servizi (ad esempio, un gruppo di fornitori di default + alcuni provider personalizzati) per registrare se stessi?

 interface FooAlgorithm
 {
     /* methods particular to this class of algorithms */
 }

 interface FooAlgorithmProvider
 {
     public FooAlgorithm getAlgorithm(Configuration c);
 }

 class FooAlgorithmRegistry
 {
     private FooAlgorithmRegistry() {}
     static private final Map<String, FooAlgorithmProvider> directory =
        new HashMap<String, FooAlgorithmProvider>();
     static public FooAlgorithmProvider getProvider(String name)
     {
         return directory.get(serviceName);
     }
     static public boolean registerProvider(String name, 
         FooAlgorithmProvider provider)
     {
         if (directory.containsKey(name))
            return false;
         directory.put(name, provider);
         return true;
     }
 }

es. se scrivo classi personalizzate MyFooAlgorithm e MyFooAlgorithmProvider per implementare FooAlgorithm, e li distribuisco in un barattolo, c'è qualche modo per ottenere registerProvider di essere chiamato automaticamente, o saranno i miei programmi client che utilizzano l'algoritmo necessario chiamare esplicitamente FooAlgorithmRegistry.registerProvider () per ogni classe che vogliono usare?

È stato utile?

Soluzione

Credo che hai bisogno di creare un META-INF / services / fully.qualified.ClassName ed elencare le cose lì, ma io non ricordo le specifiche ( JAR File Specifica o questo ).

API Pratica confessioni di progettazione di un architetto Java libro capitolo 8 è di circa SPI.

Il ServiceLoader potrebbe aiutare di elencare le implementazioni disponibili. Per esempio con l'interfaccia PersistenceProvider:

ServiceLoader<PersistenceProvider> loader = 
        ServiceLoader.load(PersistenceProvider.class);
Iterator<PersistenceProvider> implementations = loader.iterator();
while(implementations.hasNext()) {
    PersistenceProvider implementation = implementations.next();
    logger.info("PersistenceProvider implementation: " + implementation);
}

Altri suggerimenti

Si potrebbe avere registrare il JAR cliente i fornitori in un blocco di inizializzazione statica all'interno di alcuni di classe che si sa sarà chiamato prima FooAlgorithmRegistry.getProvider(), qualcosa come:

static {
    FooAlgorithmRegistry.registerProvider("test", new MyFooAlgorithmProvider());
}

Ma, potrebbe essere piuttosto difficile trovare un modo per garantire che questo verrà eseguito (inizializzatori statici sono garantiti per essere eseguito una sola volta e solo una volta, quando la classe viene prima caricato) prima che il metodo di accesso della fabbrica.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top