7

I have enum CarBrand:

public enum CarBrand {
    BMW, MERCEDES, VOLKSWAGEN, AUDI, FORD, OPEL
}

and enum CarBodyType:

public enum CarBodyType {
    SEDAN, MINIVAN, VAN
}

Relationship between them is many to many. I.e. a car brand can have several variants of type of car body, and a car body type has several brands.

How to define such entity–relationship model in my code with these enums?

Maybe I need make field in each enum as a set parameterized by another enum?

public enum CarBrand {
    BMW, MERCEDES, VOLKSWAGEN, AUDI, FORD, OPEL;

    private Set<CarBodyType> bodyTypes;         

    public Set<CarBodyType> getBodyTypes() {
       return bodyTypes;
    }

    public void setBodyTypes(Set<CarBodyType> bodyTypes) {
       this.bodyTypes = bodyTypes;
    }
}

and

public enum CarBodyType {
    SEDAN, MINIVAN, VAN;

    private Set<CarBrand> brands;

    // getter and setter
}

Is this a good solution? Or would it be better to implement such relationships via a third junction entity? If so, what should it be? How should this entity be designed and what fields should it contain?

Beth Lang
  • 1,889
  • 17
  • 38
François Esthète
  • 855
  • 2
  • 9
  • 15

3 Answers3

4

It is almost certainly not true that a body-type "has a" brand. It is most likely not true that a brand "has a" body type. What you most likely want to model is a separate set of the intersection of each brand's permissible body types.

That is you most likely want a Vehicle which has a body-type and a brand:

public class Vehicle 
{
    private CarBrand brand;
    private CarBodyType body;
    ...
}

and create Vehicles each of which model one combination.

In response to the comment

For example what about this case? If Book and Author are enums.

I don't think the book/author example works for enums (and maybe your use of enums is at the heart of the problem). The number of books and authors is open-ended; you wouldn't model either books or authors using a closed-set enum. Further more, it is true that every book has one or more authors, while every author is only an author in the context of having written one or more books (otherwise they are simply a person aspiring to be an author).

In relational modelling of books and authors you would have a Book table, an Author table and a separate relation table of BookAuthor which was a conjunction of foreign keys to the Book and Author tables. In object terms change the word "table" to "object", though in an object model you would probably replace the BookAuthor "table" with a set of authors in each book and/or a set of books in each author.

Lawrence Dol
  • 63,018
  • 25
  • 139
  • 189
  • @Bhesh: Except that arguably Minivan and a Van are not cars... I used Vehicle to highlight this to the OP. What I think is wrong at that level is his/her use of `Car`. – Lawrence Dol Dec 15 '12 at 01:34
  • Thanks! Is this only solution? It is always necessary to create third junction entity? Or am I just chose not the best sample? For example what about [this case](http://en.wikipedia.org/wiki/Many-to-many_(data_model))? If `Book` and `Author` are enums. Is your solution common and actual for this example too? Or is it just for my specific situation? – François Esthète Dec 16 '12 at 07:12
0

It is not good practice to have circular dependencies like this.

If you need to keep such a relation, keep it in a separate class, which avoid circularities.

Bohemian
  • 412,405
  • 93
  • 575
  • 722
0

Then your CarBrand class seems to be a more complicated structure that Enum. It can be still a value type with some kind of identity map inside though:

class CarBrand {

    static Set<CarBrand> AllBrands;  //replacement for CarBrand enum
    static Set<CarBodyType> GetTypes(CarBrand brand) { /* search this.AllBrands here */} 
    static Set<CarBrand> GetBrands(CarBodyType type) { /* search this.AllBrands here */} 

    /*specify types per brand */
    Set<CarBodyType> bodyTypes;
}

If you prefer to go on with CarBrand enum, this can be also done as an explicit third relationship structure. Introduce association class:

class CarBrandTypePair {
    CarBrand, CarBodyType,
}

and the rest should be as the static part of CarBrand sample above.

First way is more extensible probably: you'd add in future some other brand's specific. With second approach you'd add more and more simple associations.

mikalai
  • 1,746
  • 13
  • 23