Что является лучшей практикой программирования на Java: сложение перечислений и конструкторов перечислений или создание подклассов? - PullRequest
7 голосов
/ 21 апреля 2010

Учитывая конечное число элементов, которые различаются по виду, лучше ли представлять их с помощью сложенных перечислений и конструкторов перечислений или создавать их подклассы? Или вообще есть лучший подход?

Чтобы дать вам некоторый контекст, в моей маленькой RPG-программе (которая, по иронии судьбы, должна быть простой), персонаж имеет различные виды предметов в своем инвентаре. Предметы различаются в зависимости от их типа, использования и эффекта.

Например, один предмет инвентаря - это свиток заклинаний под названием Gremlin, который регулирует атрибут Utility. Другим предметом может быть меч по имени Морт, который используется в бою и наносит урон.

В моем коде 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 ]

8 голосов
/ 21 апреля 2010

Перечисления хороши, если хранятся только статические данные и очень минимально логичны (желательно без логики). Если ваши объекты должны иметь различное поведение в зависимости от их вида, обычно рекомендуется реализовать их как подклассы.

Как уже упоминалось, вы, скорее всего, добавите атрибуты к своим объектам, и эти атрибуты не будут иметь смысла для всех видов. Например. атрибут цвета имеет смысл для оружия, но не для заклинания. В этом случае оружие и заклинание не должны быть в одном и том же перечислении.

6 голосов
/ 21 апреля 2010

В контексте, который вы описываете, я хотел бы рассмотреть возможность использования иерархии классов в отличие от определений enum и дополнения этой иерархии интерфейсами; например,

/**
 * 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 с или как список Usable с). Другая причина, по которой я бы держался подальше от перечислений, заключается в том, что вы, скорее всего, определяете поведение своих предметов (например, spell.cast(Person)), а в перечислениях это не очень хорошо.

6 голосов
/ 21 апреля 2010

Если вы хотите добавить новые атрибуты к элементам, может быть проще реализовать их как подклассы. Таким образом, если группа элементов получает новый атрибут, она распространяется на все подклассы.

Например, если все виды Weapon получают определенный вес, назначенный ему, вы просто добавляете этот атрибут в этот класс. Этот атрибут затем будет распространяться на подклассы.

Что касается других вещей, которые более статичны по своей природе и, таким образом, могут напрямую назначаться типу, перечисления хороши. Я свободно размышляю здесь, поэтому я предполагаю, что Weapon может быть назначен DamageType:

public abstract class Weapon {

public enum DamageType {

 CUT,
 SMASH,
 PIERCE;
}

private DamageType damageType;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...