2017-05-17 5 views
4

J'ai cette classe qui enveloppe un objet:Comment éviter de répéter un code complexe de gestion des exceptions dans une classe wrapper?

public class MyWrapper implements MyInterface { 

    private MyInterface wrappedObj; 

    public MyWrapper(MyInterface obj) { 
     this.wrappedObj = obj; 
    } 

    @Override 
    public String ping(String s) { 
     return wrappedObj.ping(s); 
    } 

    @Override 
    public String doSomething(int i, String s) { 
     return wrappedObj.doSomething(i, s); 
    } 

// many more methods ... 
} 

Maintenant, je veux ajouter la gestion des exceptions complexes autour de l'appel wrappedObj.

Il en est de même pour toutes les méthodes. Comment puis-je éviter de répéter encore et encore le même code de gestion des exceptions?

+0

Je pense que nous aurions besoin de voir ce que «complexe» implique. Normalement, je viens de mettre les parties dupliquées dans une méthode commune et appelez si nécessaire. – markspace

+0

C# équivalent [Comment utiliser essayer attraper bien dans plusieurs méthodes?] (Http://stackoverflow.com/questions/23423043/how-to-use-try-catch-nicely-in-multiple-methods) –

+0

Définir 'private handle vide (exception MyException) 'et l'appelle de chaque bloc' catch'? – VGR

Répondre

0

Si votre traitement d'exception est vous complètement générique pourrait mettre en œuvre l'emballage comme InvocationHandler:

public class ExceptionHandler implements java.lang.reflect.InvocationHandler { 
    public ExceptionHandler(Object impl) { 
     impl_ = impl; 
    } 

    @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
     try { 
      return method.invoke(impl_, args); 
     } 
     catch (Exception e) { 
      // do exception handling magic and return something useful 
      return ...; 
     } 
    } 

    private Object impl_; 
} 

puis l'enrouler autour d'une instance comme suit:

MyInterface instance = ... 
MyInterface wrapper = (MyInterface)java.lang.reflect.Proxy.newProxyInstance(
    instance.getClass().getClassLoader(), 
    new Class[] { MyInterface.class }, 
    new ExceptionHandler(instance)); 

wrapper.ping("hello"); 
0

Si vous voulez éviter le coût de la réflexion, que d'utiliser simplement une fonction de routeur.

@Override 
public String ping(String s) { 
    return (String) call("ping"); 
} 

private Object call(String func) { 
    try { 
     switch(func) { 
     case "ping": return wrappedObj.ping(s); 
     // ... rest of functions ... // 
     } 
    } catch(Exception e) { 
     log(e); 
    } 
} 

Le compilateur peut effectivement passer directement à la fonction sans extraire les spécifications ou gestionnaires d'objet. (Un compilateur assez intelligent peut même simplement compiler ce code d'exécution identique à votre code actuel, surtout si vous pouvez couper la distribution en retournant toujours le même type d'objet)

Si vous ne vous souciez pas du fil et juste veulent un gestionnaire d'exception par défaut ...

pour l'ensemble Java Runtime, appelez Thread.setDefaultUncaughtExceptionHandler
pour ThreadGroup, passer outre ThreadGroup.uncaughtException
pour un seul thread, appelez Thread.setUncaughtExceptionHandler

l'avantage d'un gestionnaire par défaut, est que tu c puis ajouter des gestionnaires d'erreurs spécifiques si nécessaire, mais le côté négatif est que vous perdez le thread en cours d'exécution en cas d'erreur.