2010-04-21 2 views
7

Étant donné un nombre fini d'éléments qui diffèrent en nature, est-il préférable de les représenter avec des énumérateurs empilés et des constructeurs d'énumération, ou de les sous-classer? Ou y a-t-il une meilleure approche?Quelle est la meilleure pratique de programmation Java: empiler des enums et constructeurs enum, ou sous-classes?

Pour vous donner un contexte, dans mon petit programme RPG (qui est censé être simple ironie du sort), un personnage a différentes sortes d'objets dans son inventaire. Les éléments diffèrent en fonction de leur type, de leur utilisation et de leur effet.

Par exemple, un élément de l'inventaire est un rouleau de sort appelé Gremlin qui ajuste l'attribut Utility. Un autre objet pourrait être une épée appelée Mort qui est utilisée en combat et inflige des dégâts.

Dans mon code RPG, j'ai maintenant essayé deux façons de représenter les éléments de l'inventaire. Une façon était de sous-classer (par exemple, InventoryItem -> Spell -> AjusterAttributs, InventoryItem -> Weapon -> Epée) et d'instancier chaque sous-classe si nécessaire, et d'assigner des valeurs telles que Gremlin et Mort.

L'autre façon consistait à empiler des énumérateurs et des constructeurs d'énumération. Par exemple, j'ai créé énumérations pour itemCategory et itemSpellTypes et itemWeaponTypes et le ENUM InventoryItem était comme ça:

public enum InventoryItem { 
    GREMLIN(itemType.SPELL, itemSpellTypes.ATTRIBUTE, Attribute.UTILITY), 
    MORT(itemType.WEAPON, itemWeaponTypes.SWORD, 30); 

    InventoryItem(itemType typeOfItem, itemSpellTypes spellType, Attribute attAdjusted) { 
    // snip, enum logic here 
    } 
    InventoryItem(itemType typeOfItem, itemWeaponTypes weaponType, int dmg) { 
    // snip, enum logic here 
    } 
    // and so on, for all the permutations of items. 

} 

est-il une meilleure pratique de programmation Java que ces deux approches? Ou si ce sont les seuls moyens, lequel des deux est le meilleur? Merci en avance pour vos suggestions.

Répondre

6

Dans le contexte que vous décrivez, j'envisager d'utiliser une hiérarchie de classes par opposition à enum définitions et complétant cette hiérarchie avec des interfaces ; par exemple.

/** 
* Root of class hierarchy. 
*/ 
public interface InventoryItem { 
} 

/** 
* Additional "parallel" interface implemented by some (but not all) 
* InventoryItems and other non-inventory items. 
*/ 
public interface Usable { 
    void use(); 
} 

/** 
* A Spell is in InventoryItem and is also Usable. 
*/ 
public abstract class Spell implements InventoryItem, Usable { 
} 

public class Gremlin extends Spell { 
} 

/** 
* A Door is *not* an InventoryItem but can be used. 
*/ 
public class Door implements Usable { 
} 

L'avantage principal de cette approche est qu'il vous permet de traiter un objet donné dans différents contextes (comme InventoryItem s ou une liste de Usable s). L'autre raison pour laquelle je voudrais éviter les enums est que vous êtes susceptible de définir le comportement de vos articles (par exemple, spell.cast(Person)) et cela ne se passe pas bien à enums IMHO.

+0

+1 et en sélectionnant votre réponse en raison de l'exactitude de votre réponse et du guide du code utile. – Arvanem

8

Les énumérations sont bonnes si elles ne contiennent que des données statiques et très peu logiques (de préférence aucune logique). Si vos objets sont supposés avoir des comportements différents en fonction de leur type, c'est généralement une bonne idée de les implémenter en tant que sous-classes.

Comme d'autres ont mentionné, vous êtes très susceptibles d'ajouter des attributs à vos objets et ces attributs ne seront pas de sens pour toutes sortes. Par exemple. un attribut de couleur a du sens pour une arme mais pas pour un sort. Dans ce cas, l'arme et le sort ne devraient pas être dans la même énumération.

+0

+1 pour la réponse concise et précise.Merci Guillaume. – Arvanem

+0

+1 enums (devrait) besoin de pas de logique – stacker

6

Si vous souhaitez ajouter de nouveaux attributs aux éléments qu'il pourrait être plus facile de les mettre en œuvre des sous-classes. De cette façon, si un groupe d'éléments obtient un nouvel attribut, il se propagera à toutes les sous-classes.

Par exemple, si toutes sortes de Weapon obtient un certain poids qui lui est attribué, vous ajoutez simplement cet attribut à cette classe. Cet attribut sera ensuite propagé aux sous-classes.

En ce qui concerne d'autres choses qui sont plus statiques dans la nature, et peut donc être directement attribué un type, les énumérations sont bons. Je pense librement ici, donc je suppose un Weapon pourrait avoir un DamageType affecté à ce:

public abstract class Weapon { 

public enum DamageType { 

CUT, 
SMASH, 
PIERCE; 
} 

private DamageType damageType; 
+1

+1 pour la mise en œuvre pratique des articles. – Arvanem

Questions connexes