2010-11-27 17 views
5

J'utilise le modèle de conception Chaîne de responsabilité en Java. La chaîne dans son ensemble représente une demande d'objets de certains types. Chaque "gestionnaire" de la chaîne est responsable de gérer les unités demandées d'un type. Toutes les demandes sont traitées essentiellement de la même manière, j'ai donc essayé de rendre le générique "Handler". Ainsi, dans la poignée de classe I ont besoin d'une méthode comme celui-ci (le traitement lui-même est simplifiée car elle n'obscurcir mon problème):Gestionnaire de chaîne de responsabilité avec les génériques Java

public class Handler<T>{ 
    int required; 
    Handler<?> next; 

    public void handle(Object O){ 
     if(o instanceof T){ 
     required --; 
     }else{ 
     next.handle(o); 
     } 
    } 
} 

Le problème est qu'un instanceof comme cela est impossible. Parce que le type T n'est pas explicitement stocké pendant l'exécution (ou c'est ce que j'ai compris lors de mes recherches sur internet). Ma question est la suivante: quelle est la meilleure alternative?

Répondre

2

Mettre en oeuvre des gestionnaires utilisant des génériques en utilisant un paramètre constructeur pour définir la classe le gestionnaire prend en charge:

public class Handler<T> { 
    private int required; 
    private Handler<?> next; 
    private Class<? extends T> c; 

    public Handler(Class<? extends T> c) { 
     this.c = c; 
    } 

    public void handle(Object o) { 
     if (c.isInstance(o)) { 
      required--; 
     } else { 
      next.handle(o); 
     } 
    } 

    // ... 
}  
+0

en effet .... cela fonctionne pour le niveau d'objet supérieur, mais les génériques semblent être par défaut 'Object' dans les signatures de méthode au moment de la compilation. En tous cas. La deuxième solution est supprimée, mais la première solution reste bien dans ce que vous essayez d'atteindre –

+0

c'est le plus proche de la solution que je voulais atteindre, merci. Maintenant, je peux laisser tomber la partie générique, parce que je peux tout faire avec la classe comme argument – Ingdas

1

Il serait laid, mais vous pouvez essayer ceci:

public abstract class Handler { 
    int required; 
    Handler next; 

    public void handle(Object o){ 
     if(getMyClass().isInstance(o)){ 
     required --; 
     }else{ 
     next.handle(o); 
     } 
    } 

    protected abstract Class getMyClass(); 
} 
+0

+1 - Il fonctionne, et il est vraiment pas tout ce que laid. –

+0

Est-ce que 'getClass' n'est pas défini comme' public' sur 'java.lang.Object'? Il semble que vous essayez de le remplacer par un niveau d'accès plus strict. –

+0

Et si vous choisissez un nom différent, alors 'Class' devrait avoir un paramètre de type:' protected abstract Classe getHandledValueType(); ' –

1

On dirait que vous ne l'utilisez en fait une chaîne du tout, à moins que vous avez des cas où les deux base et sous les classes coup d'envoi des événements . Si cette partie, à moins ne s'applique pas, vous pouvez faire quelque chose comme

Map<Class, Handler> handlers = //...initialize however 

et gestionnaire racine: si vous appelez poignée sur

public void handle(Object o) { 
handlers.get(o.getClass()).handle(o); 
} 
0

Il n'a pas de sens d'avoir un gestionnaire en utilisant les génériques chaque objet. Soit vous instancier un gestionnaire pour le type comme ceci:

public class Handler<T>{ 
    int required; 
    Handler<?> next; 

    public void handle(T O){ 
    ... 
    } 
} 

ou vous définissez un gestionnaire de classe abstraite et laissez-la sous-classe spécifique pour gérer le type spécifique ou juste passer l'événement à la chaîne. utilisant également

if(x.isInstance(o)) {...} 

est vraiment un antimodèle et vous pouvez briser les règles de POO.