2016-12-02 2 views
0

Ich versuche, meinen Code aufzuräumen, da ich viele verschiedene Klassen habe, die initialisiert werden müssen, bevor mein Programm bereit ist, seine Aufgaben zu erledigen.
Sie sind alle optional und können fehlschlagen, aber einer von ihnen muss erfolgreich sein.
Alle diese Klassen implementieren eine Schnittstelle namens Hook.Aufruf des Konstruktors eines anderen Objekts auf jedem Index von Array/Collection

Jede Initialisierung in eine HashMap gesetzt wird, ist hier ein Beispiel:

HashMap<String, Hook> hooks = new HashMap<>(); 
String key = "Fish"; 
if (isEnabled(key)) { 
try { 
    hooks.put(key, new FishStoreHook()); 
} catch { 
    logError(key); 
} 
} 

Aber jetzt muss ich für ein anderes haben, sagen Brot:

key = "Bread"; 
if (isEnabled(key)) { 
try { 
    hooks.put(key, new BreadStoreHook()); 
} catch { 
    logError(key); 
} 
} 

Gibt es eine Möglichkeit zu setzen etwas in einem Array oder einer Sammlung, so dass sie mit einer für jede Aussage aufgerufen werden können?

(Grund sie in eine HashMap gestellt werden, weil ihre Methoden mit einem Lauf für jeden HashMap.keySet() und ich brauche mögliche Fehler zu protokollieren)
Vielen Dank im Voraus!

Antwort

0

Ich würde vorschlagen, die die Reflexion:

String className = "package.name." + key + "StoreHook"; 
Class<Hook> clazz = (Class<Hook>) YourClass.class.forName(className); 
Hook hook = clazz.newInstance(); 

OR Wenn Sie Spring verwenden, können Sie auch alle Untertypen von Hook erhalten.

ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false); 
provider.addIncludeFilter(new AssignableTypeFilter(Hook.class)); 
Set<BeanDefinition> definitions = provider.findCandidateComponents("package/name"); 

Map<String, Hook> hooks = new HashMap<>(); 
for (BeanDefinition definition : definitions) { 
    try { 
     Class clazz = Class.forName(definition.getBeanClassName()); 
     hooks.put(clazz.getSimpleName(), clazz.newInstance()); 
    } catch (ClassNotFoundException e) { 
     logger.error("Unable to get class: ", e); 
    } 
} 

Und dann können Sie Ihre Instanz von hashmap zu bekommen.

+1

Reflektion hat perfekt funktioniert, vielen Dank! :) Code von 150 Zeilen auf 17 reduziert, absolut fantastisch. Obwohl mein Konstruktor Argumente hatte, habe ich es geschafft, das mit 'clazz.getConstructor (Plan.class) .newInstance (this)' zu starten –

0

können Sie fügen alle Hook Objekte zu einem List und dann eine for-each verwenden, wie in dem unten stehenden Code mit Inline-Kommentare angezeigt:

List<Hook> hooks = new ArrayList<>(); 
hooks.add(new FishStoreHook("Fish"));//Pass HookName as a constructor arg 
hooks.add(new BreadStoreHook("Bread"));//Pass HookName as a constructor arg 
//add other hook objects 

//Now iterate all the hook objects using foreach 
for(Hook hook : hooks) { 
    if(isEnabled(hook.getName())) {//get HookName (set through constrcutor above) 
    try { 
      hooks.put(key, hook); 
     } catch { 
       logError(key); 
      } 
     } 
    } 
+0

Ah Danke für die Antwort. Vielleicht war ich nicht sehr klar, aber wenn ich den Konstruktor aufruft, versucht es Methoden einer anderen .jar zu verwenden, die eine optionale Bibliothek ist - falls die Bibliothek nicht existiert, gibt der Konstruktor einen Fehler aus, wenn er ausgeführt wird. –

0
@SuppressWarnings("serial") 
    final Map<String, Callable<Hook>> init = 
     new LinkedHashMap<String, Callable<Hook>>() {{ 
      put("Fish", new Callable<Hook>() { 
       @Override public Hook call() throws Exception { 
        return new FishStoreHook(); }}); 
      put("Bread", new Callable<Hook>() { 
       @Override public Hook call() throws Exception { 
        return new BreadStoreHook(); }}); 
     }}; 

    final Map<String, Hook> hooks = new HashMap<>(); 
    for(Map.Entry<String, Callable<Hook>> e: init.entrySet()) 
     try { 
      if(isEnabled(e.getKey())) 
       hooks.put(e.getKey(), e.getValue().call()); 
     } catch(Exception ex) { 
      logError(e.getKey()); 
     } 

Sie benötigen die LinkedHashMap, falls Sie über die Reihenfolge kümmern, sonst nur jede Art von Map tun würde.

Verwandte Themen