Что такое хорошая структура данных для представления поля, которое является более сложным, чем перечисление, но не совсем классом? - PullRequest
3 голосов
/ 13 февраля 2011

Я пишу программу, которая связана с греблей, и я создаю неизменный класс с именем «BoatType» для представления различных «типов» лодок, которые существуют. Это становится сложным, потому что есть много типов, которые требуют уникального описания.

BoatType должен иметь следующее:

  • Тип SCULL или SWEEP
  • Число, которое соответствует количеству людей, которые помещаются в лодку.
  • Тип PORT или STARBOARD, но только если первый тип SWEEP
  • Логическое значение, представляющее COXED или UNCOXED, как правило, только для SWEEP

Это еще более осложняется тем фактом, что в мире гребли существуют только определенные комбинации этих полей. Мне бы хотелось, чтобы моя программа имела простой перечислимый доступ к этим стандартным типам без необходимости создавать новые объекты BoatType. Это в полном объеме:

SCULL 8
SCULL 4
SCULL 2
SCULL 1
SWEEP 8 ПОРТ COXED
SWEEP 8 STARBOARD COXED
SWEEP 4 ПОРТ COXED
ПОРТ SWEEP 4 UNCOXED
SWEEP 4 STARBOARD COXED
SWEEP 4 STARBOARD UNCOXED
SWEEP 2 ПОРТ COXED
SWEEP 2 ПОРТ UNCOXED
SWEEP 2 STARBOARD COXED
SWEEP 2 STARBOARD UNCOXED

В настоящее время это класс, который я написал на Java:

public class BoatType
{
public enum RiggerType{SCULL, SWEEP_PORT, SWEEP_STARBOARD}

private int numSeats;

private RiggerType riggerType;

public boolean coxswain = true;

public BoatType(RiggerType type, int seats, boolean coxed)
{
    numSeats = seats;
    riggerType = type;
    coxswain = coxed;
}
}

с перечислением стандартных типов в другом месте:

    public static final BoatType 
    SCULL_OCTUPLE = new BoatType(RiggerType.SCULL, 8, false),
    SCULL_QUAD = new BoatType(RiggerType.SCULL, 4, false),
    SCULL_DOUBLE = new BoatType(RiggerType.SCULL, 2, false),
    SCULL_SINGLE = new BoatType(RiggerType.SCULL, 1, false),
    SWEEP_PORT_EIGHT_COXED  = new BoatType(RiggerType.SWEEP_PORT, 8, true),
    SWEEP_STARBOARD_EIGHT_COXED = new BoatType(RiggerType.SWEEP_STARBOARD, 8, true),
    SWEEP_PORT_FOUR_COXED = new BoatType(RiggerType.SWEEP_PORT, 4, true),
    SWEEP_PORT_FOUR_UNCOXED = new BoatType(RiggerType.SWEEP_PORT, 4, false),
    SWEEP_STARBOARD_FOUR_COXED = new BoatType(RiggerType.SWEEP_STARBOARD, 4, true),
    SWEEP_STARBOARD_FOUR_UNCOXED = new BoatType(RiggerType.SWEEP_STARBOARD, 4, false),
    SWEEP_PORT_PAIR_COXED = new BoatType(RiggerType.SWEEP_PORT, 2, true),
    SWEEP_PORT_PAIR_UNCOXED = new BoatType(RiggerType.SWEEP_PORT, 2, false),
    SWEEP_STARBOARD_PAIR_COXED = new BoatType(RiggerType.SWEEP_STARBOARD, 2, true),
    SWEEP_STARBOARD_PAIR_UNCOXED = new BoatType(RiggerType.SWEEP_STARBOARD, 2, false);

В настоящее время это кажется довольно громоздким, поэтому мне было интересно, есть ли у кого-нибудь лучшая идея, как это представить. Перечисление не может быть и речи, потому что, хотя эти стандартные типы существуют, я не хочу ограничивать их этими комбинациями.

Ответы [ 4 ]

4 голосов
/ 13 февраля 2011

Я думаю, что ваш класс в основном в порядке, за исключением того, что:

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

  • Вы должны поместить константы и коллекцию для стандартных типов внутри класса, а не в другом месте.

  • Добавьте обычную инфраструктуру (toString, hashCode, equals, геттеры).

  • Все переменные экземпляра должны быть private (coxswain не) и final.

Да, это немного громоздко, но такова Java. Такая среда, как Eclipse, может помочь, сгенерировав часть этого кода.

3 голосов
/ 13 февраля 2011

Вы можете сделать BoatType абстрактным и создать два подкласса BoatType, а именно ScullBoatType и SweepBoatType.Затем вы можете определить два логических поля "isPort" и "isCoxed" в SweepBoatType (но не в ScullBoatType).Например:

abstract class BoatType {
    protected int numSeats;

    public BoatType(int numSeats) {
            this.numSeats = numSeats;
    }
}

final class ScullBoatType extends BoatType {
    public ScullBoatType(int numSeats) {
        super(numSeats);
    }
}

final class SweepBoatType extends BoatType {
    private boolean isPort;
    private boolean isCoxed;

    public SweepBoatType(int numSeats, boolean isPort, boolean isCoxed) {
        super(numSeats);
        this.isPort = isPort;
        this.isCoxed = isCoxed;
    }
}

Новые экземпляры могут быть созданы следующим образом:

BoatType SCULL_OCTUPLE = new ScullBoatType(8);
BoatType SWEEP_PORT_EIGHT_COXED = new SweepBoatType(8, true, true);
// and so on...
1 голос
/ 13 февраля 2011

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

Одна заметка, вы можете захотеть иметь постоянную видимость для членов BoatType и сделать всеэти члены финал.

1 голос
/ 13 февраля 2011

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

http://download.oracle.com/javase/tutorial/java/javaOO/enum.html

http://www.basilv.com/psd/blog/2006/advanced-uses-of-java-5-enums

...