2010-06-29 20 views
3

Supposons que j'ai:Existe-t-il un moyen meilleur/plus propre de créer un type avec condition que d'utiliser instanceof? [Java]

public class FightingZone<MobileSuitso, Background> { 

    private MobileSuitCollection<MobileSuitso> msCollection; 
    private BackgroundInfo<Background> bgInfo; 

    public FightingZone(MobileSuitCollection<MobileSuitso> newCollection, BackgroundInfo<Background> newInfo) { 
     this.msCollection = newCollection; 
     this.bgInfo = newInfo; 
    } 

    ... 

     ...// inside a method 
     MobileSuitCollection temporaryCollection = new MobileSuitCollection<MobileSuitso>(); // /!\ 

} 

Le problème est MobileSuitCollection est une interface, je ne peux pas instancier. Par exemple, je pouvais faire:

MobileSuitCollection temporaryCollection = new GundamMeisterCollection<MobileSuitso>(); 
MobileSuitCollection temporaryCollection = new InnovatorCollection<MobileSuitso>(); 
MobileSuitCollection temporaryCollection = new CannonFolderCollection<MobileSuitso>(); 

etc. Cependant, pour manipuler temporaryCollection, je en ai besoin d'être du même type que celui passé par paramètre à ma classe. J'ai donc pensé à faire ceci:

if (msCollection instanceof GundamMeisterCollection) { 
    ... 
} else if (msCollection instanceof InnovatorCollection) { 
    ... 
} ... 

Je réalise que c'est affreux cependant. Y a-t-il une meilleure manière de faire cela? Serait-il possible de conserver une référence à la classe utilisée par le type initial, puis d'instancier le temporaryCollection avec cela?

Répondre

2

Le code que vous placez dans la si la clause peut être placé dans un Visitor:

// Generics skipped for brevity 
interface MobileSuitCollectionVisitor { 
    handleCollection(GundamMeisterCollection collection); 
    handleCollection(InnovatorCollection collection); 
    handleCollection(CannonFolderCollection collection) 
} 

class ConcreteVisitor implements MobileSuitCollectionVisitor { 
    // place all of the logic in the implemented methods 
} 

puis laisser MobileSuitCollection ont une méthode:

void visit(MobileSuitCollectionVisitor visitor); 

Et dans chaque mise en œuvre de MobileSuitCollection simplement avoir

public void visit(MobileSuitCollectionVisitor visitor) { 
    visitor.handleCollection(this); 
} 
+0

Je cherchais à utiliser Reflection pour obtenir le nom de classe et l'instancier à partir de là. Supposons que cela soit possible, cela ne rendrait-il pas le code plus propre? Ou est-ce toujours l'approche préférée? –

+0

Si vous utilisez Reflection, utilisez l'objet de classe au lieu du nom de classe. Comme ça: 'Classe cl = collection.getClass(); Interface inst = cl.newInstance();' –

+0

La réflexion devrait être le dernier recours. L'approche ci-dessus est l'approche orientée objet. – Bozho

0

Un moyen rapide et sale le faire serait de cloner la collection originale, puis de la manipuler au besoin. Un meilleur moyen pourrait être d'ajouter une méthode newInstance() à l'interface, ou passer dans une usine à FightingZone.