哪种更好的Java编程实践:堆栈枚举和枚举构造函数,或子类化?

时间:2010-04-21 07:28:02

标签: java enums subclassing multiple-constructors

鉴于有限数量的项目有所不同,用堆叠的枚举和枚举构造函数表示它们还是将它们子类化更好?或者是否有更好的方法?

为了给你一些背景知识,在我的小型RPG程序中(具有讽刺意味的是,它应该很简单),角色在他或她的库存中有不同种类的物品。项目因类型,用途和效果而异。

例如,一个库存项目是一个名为Gremlin的拼写滚动,用于调整Utility属性。另一件物品可能是一把名为Mort的剑,用于战斗并造成伤害。

在我的RPG代码中,我现在尝试了两种表示库存项目的方法。一种方法是子类化(例如,InventoryItem - > Spell - > AdjustingAttributes; InventoryItem - > Weapon - > Sword)并在需要时实例化每个子类,并分配诸如Gremlin和Mort等名称之类的值。

另一种方法是堆叠枚举和枚举构造函数。例如,我为itemCategory和itemSpellTypes以及itemWeaponTypes创建了枚举,而InventoryItem枚举是这样的:

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. 

}

是否有比这两种方法更好的Java编程实践?或者,如果这些是唯一的方式,哪两个更好?提前感谢您的建议。

3 个答案:

答案 0 :(得分:8)

如果只保留静态数据并且逻辑非常小(最好没有逻辑),则枚举很好。如果您的对象根据其类型具有不同的行为,那么将它们作为子类实现通常是个好主意。

正如其他人所提到的,您很可能会为对象添加属性,而这些属性对于所有类型都没有意义。例如。颜色属性对于武器有意义,但对于法术则没有意义。在这种情况下,武器和法术不应该在同一个枚举中。

答案 1 :(得分:6)

如果要为项添加新属性,可以更容易地将它们实现为子类。这样,如果一组项目获得一个新属性,它将传播到所有子类。

例如,如果所有类型的Weapon都分配了一定的权重,您只需将该属性添加到该类即可。然后,该属性将传播到子类。

关于其他更静态的东西,因此可以直接分配类型,枚举很好。我在这里自由思考,所以我想Weapon可以分配DamageType

public abstract class Weapon {

public enum DamageType {

 CUT,
 SMASH,
 PIERCE;
}

private DamageType damageType;

答案 2 :(得分:6)

在您描述的上下文中,我将考虑使用类层次结构而不是枚举定义,并使用接口补充此层次结构; e.g。

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

这种方法的主要优点是它允许您在不同的上下文(作为InventoryItem s或Usable的列表)处理给定对象。我要避开枚举的另一个原因是你可能会在你的项目上定义行为(例如spell.cast(Person)),而这在IMHO的枚举中效果不佳。