2010-06-24 4 views
2

Disons que j'ai beaucoup de classes similaires (unités dans un RTS dans cet exemple), qui est, la classe Unit, et les sous-classes UnitA, UnitB, UnitC etc.Java Mauvais motif?

Toutes les classes de parts ont le constructeur suivant (unité comprenant)

public class UnitX { 
    public UnitX(FileReader fr) { 
     ...read parameters for constructing the unit... 
    } 
} 

Mon fichier contenant les paramètres ont la forme

UnitX params 
UnitY params 
.... 

et la création d'une liste de toutes les unités dans un fichier serait une boucle while comme

Class[] params = {FileReader.class}; 
while(fr has more to read) { 
    String unitType = fr.getString(); 
    Unit u = (Unit) 
java.lang.reflect.Constructor constr = Class.forName(unitType).getConstructor(params); 
    Unit u = (Unit)constr.newInstance(new Object[]{fr}); 
    list.add(u); 
} 

je réalisais que j'utilise ce modèle très souvent quand je crée des objets à partir de fichiers. Ma question est, est-ce un mauvais modèle? Y a-t-il une meilleure manière de faire cela?

Répondre

2

Le code lui-même est correct. Puisque les constructeurs ne peuvent pas faire partie d'une interface codifiée traditionnelle, la meilleure chose à faire est l'interface réfléchissante cohérente. Cependant, si vous répétez ce code dans plusieurs endroits, ce n'est pas très bon. Vous pouvez essayer de centraliser cela dans une sorte d'usine ou de constructeur qui fournit les noms d'unités du fichier, ainsi que les paramètres définis pour cette unité, et l'associer à une implémentation de gestionnaire qui instancie l'unité avec les paramètres fournis par UnitFactory. UnitFactory utilise la réflexion pour instancier l'unité nommée et lui fournir les paramètres.

Cela permet de réutiliser et découpler la lecture du fichier d'instanciation et la méthode d'instanciation.

+0

N'est-il pas plus raisonnable que les classes d'unités fournissent elles-mêmes la méthode de lecture/écriture de leurs états à un lecteur/enregistreur de filer ? Une classe d'unité supplémentaire ne nécessiterait pas de modification de ma classe d'usine. –

+0

Oui, c'est aussi possible, mais sachez que vous êtes en train de mélanger les responsabilités, mais tant que vous êtes conscient de cela et de ce que cela signifie, alors c'est ok. Les tests unitaires sont généralement intentionnellement simples, de sorte qu'une approche couplée plus directe est souvent la meilleure solution, car elle est plus claire. – mdma

0

Il s'agit d'une sérialisation simplifiée. Je dirais que c'est bien si cela correspond à vos objectifs.

1

Je pense que votre implémentation est correcte. Une autre approche: le fichier texte est une forme simple d'un DSL (Domain Specific Language)

Vous pouvez passer à une langue compatible jvm plus dynamique. Les langages dynamiques comme groovy (mon préféré ;-)), javascript (Rhino, ...), BeanShell, jython, ... peuvent être plus facilement utilisés pour implémenter des langages spécifiques au domaine (DSL). Pour les DSL plus complexes, vous pouvez jeter un oeil au projet eclipse XText.

3

Ce cas pour la factory pattern:

java.lang.reflect.Constructor constr = Class.forName(unitType).getConstructor(params); 
Unit u = (Unit)constr.newInstance(new Object[]{fr}); 

pourrait être changé en

Unit u = UnitFactory.create(unitType, fr); 

L'usine est alors une liste de if/else bien.