2010-04-21 8 views
7

Dado un número finito de elementos que difieren en su tipo, ¿es mejor representarlos con enums apilados y constructores enum, o subclonarlos? ¿O hay un mejor enfoque en conjunto?¿Cuál es la mejor práctica de programación de Java: apilar enums y enum constructores, o subclases?

Para darle un poco de contexto, en mi pequeño programa de rol (que irónicamente se supone que es simple), un personaje tiene diferentes tipos de elementos en su inventario. Los artículos difieren según su tipo, uso y efecto.

Por ejemplo, un elemento del inventario es un pergamino de hechizo llamado GREMLIN que ajusta el atributo de utilidad. Otro elemento podría ser una espada llamada Mort que se usa en combate e inflige daño.

En mi código RPG, ahora he intentado dos formas de representar elementos de inventario. Una forma era crear subclases (por ejemplo, InventoryItem -> Spell -> AdjustingAttributes; InventoryItem -> Weapon -> Sword) y crear instancias de cada subclase cuando fuera necesario, y asignar valores como nombres como Gremlin y Mort.

La otra forma fue apilando enums y enum constructores. Por ejemplo, he creado enumeraciones para itemCategory y itemSpellTypes y itemWeaponTypes, y la enumeración InventoryItem era así:

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. 

} 

¿Hay una mejor práctica de programación Java que estos dos enfoques? O si estas son las únicas formas, ¿cuál de las dos es mejor? Gracias por adelantado por tus sugerencias.

Respuesta

6

En el contexto que describes me gustaría considerar el uso de una jerarquía de clases en oposición posible enumerar las definiciones y complementar esta jerarquía con interfaces ; p.ej.

/** 
* 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 { 
} 

La principal ventaja de este enfoque es que permite tratar un objeto dado en contextos diferentes (como InventoryItem s o como una lista de Usable s). La otra razón por la que me alejaría de las enumeraciones es que es probable que defina el comportamiento en sus elementos (por ejemplo, spell.cast(Person)) y esto no le sienta bien a las enums en mi humilde opinión.

+0

+1 y seleccionando su respuesta debido a la precisión de su respuesta y la útil guía de códigos. – Arvanem

8

Las enumeraciones son buenas si las únicas contienen datos estáticos y un mínimo de lógica (preferiblemente ninguna lógica en absoluto). Si sus objetos están destinados a tener diferentes comportamientos dependiendo de su tipo, por lo general es una buena idea implementarlos como subclases.

Como han mencionado otros, es muy probable que agregue atributos a sus objetos y estos atributos no tendrán sentido para todos los tipos. P.ej. un atributo de color tiene sentido para un arma pero no para un hechizo. En ese caso, el arma y el hechizo no deberían estar en la misma enumeración.

+0

+1 para la respuesta concisa y precisa.Gracias Guillaume. – Arvanem

+0

+1 enumeraciones (debería) no necesitan lógica – stacker

6

Si desea agregar nuevos atributos a los elementos, podría ser más fácil implementarlos como subclases. De esta forma, si un grupo de elementos obtiene un nuevo atributo, se propagará a todas las subclases.

Por ejemplo, si a todos los tipos de Weapon se le asigna un cierto peso, simplemente agrega ese atributo a esa clase. Este atributo se propagará a las subclases.

En cuanto a otras cosas que son más estáticas en la naturaleza, y por lo tanto se le puede asignar directamente un tipo, las enumeraciones son buenas. Estoy pensando libremente aquí, así que supongo que un Weapon podría tener un DamageType asignado:

public abstract class Weapon { 

public enum DamageType { 

CUT, 
SMASH, 
PIERCE; 
} 

private DamageType damageType; 
+1

+1 para la implementación práctica de los elementos. – Arvanem

Cuestiones relacionadas