2

I have an inheritance hierarchy with overlap. The system knows about People that can be Clients, Providers and Agents. A person have to belong to one of these classes but can belong to two or three, i.e. one Person can be a Client and a Provider at the same time.

In the database I think that the problem is solved, one table per class (Person, Client, Provider and Agent table) and a Foreign Key from the Primary Key of the subclasses table to the Primary Key of the superclass table. (Any possible improvement will be welcome :) )

The problem comes in the Java world, I don't know the best way to map this database design to my Java POJOs. I have three possible grotty workarounds:

  • A unique class called Person, with the union of all the fields in the subclasses. This will need a discriminator field in order to know wich kind of Person is. The problem is that a Person that is not a Client but is a Provider, will have all the Client-related fields set to null.

  • A unique class called Person with all the common fields to the subclasses and three "DTO-kind" properties that holds the fields related to each subclass. This way we only have one or two fields to null instead of tens

  • One abstract class for Person and seven subclasses, one per possible combination of the three subclasses i.e. Client, Provider, Agent, ClientProvider, ClientAgent ... ClientProviderAgent. :S (of course, everyone with their corresponding interfaces)

It's a webapp. I use hibernate + spring and GWT for the UI

The question is: which is the best way to solve this problem?

2
  • What do Clients, Providers, and Agents have in common? What do they differ on? Commented Sep 27, 2010 at 16:05
  • They have in common a name, address, etc. Clients have orders, discounts, charge data. Providers have days to pay, products, and so on... Commented Sep 27, 2010 at 16:57

1 Answer 1

12

IMO inheritance is not the best way to model this, I would try composition instead.

You could have a Person class and several Role classes (implementing a common interface, or being members of a Role enum, depending on the context), with each person having one or more Roles attached.

This way you can add new role types easily, and dynamically attach/detach roles to/from a person. (You can also have persons without a role, should the need arise.)

Rough example:

interface Role {
  ...
}

final class Client implements Role {
  ...
}

final class Provider implements Role {
  ...
}

final class Agent implements Role {
  ...
}

class Person {
  List<Role> roles;
  public void addRole(Role role) { ... }
  public void removeRole(Role role) { ... }
  public Role getRoleOfType(Class<? extends Role> roleType) { ... }
}

Update: enum based example

This is applicable if the role objects have no state, thus you attach the same role instance(s) to every person.

enum Role {
  CLIENT,
  PROVIDER,
  AGENT;
  // possible members, constructor etc.
}

The Person class is almost the same as above, except that

  • I use an EnumSet instead of a List, since this is tailored specifically for enums,
  • getRoleOfType() makes no sense here, so I replaced it with hasRole().

    class Person {
      Set<Role> roles = new EnumSet<Role>();
      public void addRole(Role role) { ... }
      public void removeRole(Role role) { ... }
      public boolean hasRole(Role role) { ... }
    }
    
Sign up to request clarification or add additional context in comments.

3 Comments

Please could you be more precise? Thank you
Thank you for the edit :) One more think: Could you explain me what do you mean with "being members of a Role enum". Thank you again and sorry to be so dull :S
@xocobola, no problem, see my update :-) You may want to check out the Java Tutorial section on enums too.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.