Frage

Ich beziehe mich auf "Service Provider Framework", wie in der Diskussion Kapitel 2 der wirksamen Java, was genau der richtige Weg scheint, um ein Problem zu lösen, das ich habe, wo ich zur Laufzeit eine von mehreren Klassen instanziieren muss, basierend auf einem String Auswählen welcher Service und einen Configuration Objekt (im Wesentlichen ein XML -Snippet):

Aber wie kann ich die einzelnen Dienstleister (z. B. eine Reihe von Standardanbietern + einige benutzerdefinierte Anbieter) dazu bringen, sich selbst zu registrieren?

 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;
     }
 }

ZB, wenn ich benutzerdefinierte Klassen myfooalgorithmus und myfooalgorithmprovider schreibe, um Fooalgorithmus zu implementieren, und ich in einem Glas verteile. Gibt es eine Möglichkeit, RegisterProvider automatisch aufgerufen zu werden, oder werde mein Client -Programme, die den Algorithmus nennen. ) für jede Klasse, die sie verwenden wollen?

War es hilfreich?

Lösung

Ich denke, Sie müssen eine Meta-Inf/Dienste erstellen.JAR -Dateispezifikation oder Dies).

Das Praktische API -Design -Geständnisse eines Java -Architekten Buch Kapitel 8 handelt von SPI.

Der Serviceloader könnte Ihnen helfen, verfügbare Implementierungen aufzulisten. Zum Beispiel mit der PersistenceProvider -Schnittstelle:

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

Andere Tipps

Sie können den Kundenjar die Anbieter in einem statischen Initialisierer -Block innerhalb einer Klasse registrieren lassen, von dem Sie wissen, dass FooAlgorithmRegistry.getProvider(), etwas wie:

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

Es könnte jedoch ziemlich schwierig sein, einen Weg zu finden, um sicherzustellen, dass dies ausgeführt wird (statische Initialisierer werden garantiert einmal und nur einmal ausgeführt, wenn die Klasse zum ersten Mal geladen wird), bevor die Accessor -Methode der Fabrik.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top