开发者

What is a good data structure for representing a field that is more complex than an enum, but not quite a class?

I am writing a program that is involved with rowing, and I am creating an immutable class called "BoatType" to represent the different "types" of boats that there are. This is becoming complex because there are many types that require unique description.

A BoatType should have the following:

  • Either SCULL or SWEEP type
  • A number that is the number of people that fit in the boat
  • Either PORT or STARBOARD type, but only if the first type is SWEEP
  • A boolean representing COXED or UNCOXED, generally only for SWEEP

This is even further complicated by the fact that in the rowing world, there only exist certain combinations of those fields. I'd like my program to have easy enumerated access to these standard types without having to create new BoatType objects. These are, in full:

SCULL 8

SCULL 4

SCULL 2

SCULL 1

SWEEP 8 PORT COXED

SWEEP 8 STARBOARD COXED

SWEEP 4 PORT COXED

SWEEP 4 PORT UNCOXED

SWEEP 4 STARBOARD COXED

SWEEP 4 STARBOARD UNCOXED

SWEEP 2 PORT COXED

SWEEP 2 PORT UNCOXED

SWEEP 2 STARBOARD COXED

SWEEP 2 STARBOARD UNCOXED

Currently this is the class I have written in 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;
}
}

with a enumeration of standard types elsewhere:

    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);

This currently seems rather cumbersome, so I was wondering whether anyone had a better idea how to represent this. An enum is out of the question, because while those are the standard types in existence, I don't want to restrict it to those combinations.


I think your class is mostly fine, except that:

  • You should make the constructor private and use static factory functions, which can reuse objects for standard boat types.

  • You should put the constants and a collection for the standard types inside the class, not elsewhere.

  • Add the usual infrastructure (toString, hashCode, equals, getters).

  • All instance variables should be private (coxswain isn't) and final.

Yes, it's a bit cumbersome, but that's the way Java is. An IDE like Eclipse can help by generating some of that code.


You could make BoatType abstract and create two subclasses of BoatType, namely ScullBoatType and SweepBoatType. Then you can define two boolean fields "isPort" and "isCoxed" on SweepBoatType (but not on ScullBoatType). Like so:

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;
    }
}

New instances can then be created like this:

BoatType SCULL_OCTUPLE = new ScullBoatType(8);
BoatType SWEEP_PORT_EIGHT_COXED = new SweepBoatType(8, true, true);
// and so on...


Enum is actually more than powerful to handle the complexity you want. Are you sure it's not complex enough?

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

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


I don't see how it's all that cumbersome. It is what it is, and I don't think you're going to find a significantly cleaner way.

One note, you might want to have consistent visibility for the members of BoatType and make all of those members final.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜