1

I have a specific domain entity that has a given type and some attributes. Based on the type, it can have another set of type-depending attributes. Normally, I would create a class for each type and define the type dependent attribute on the specific classes and the common attributes on the parent class:

class AbstractParentClass {
   commonAttribute1
   commonAttribute2
}

class TypeA extends AbstractParentClass {
   typeAAttribute1
   typeAAttrubute2
}

class TypeB extends AbstractParentClass {
   typeBAttribute1
   typeBAttribute2
}

However, I have close to 300 different types and creating 300 different subclasses seems like a huge amount of classes.

The other option that I have is create a field type in a class and then have all type-dependent attributes there:

class Entity {
   type
   commonAttribute1
   commonAttribute2
   typeAAttribute1
   typeAAttribute2
   typeBAttribute1
   typeBAttribute2
}

But this will be a pain to maintain and the business logic to make sure that only fields are set that are allowed to be set for a specific type will probably be a nightmare.

Are there any other options that I didn't think about?

8
  • 7
    You can't model away complexity. If you have 300 different business objects you need to handle, you need 300 pieces of logic to handle them; classes are probably the best way of doing that. Commented Oct 20, 2023 at 8:51
  • Hmm yes, makes sense. But that would also mean 300 additional database tables that have to be maintained. Commented Oct 20, 2023 at 9:47
  • 1
    You need to approach the database differently than you do the objects in code.
    – Ccm
    Commented Oct 20, 2023 at 10:33
  • @FischerLudrian if you have additional requirements (e.g. a database) that you care about, you should mention them in your question. Commented Oct 20, 2023 at 10:52
  • 1
    You do not have to map types to one table each. Depending on your requirements it may be fine to store objects as a document/json/blob. But it would be useful if you could describe the actual problem in more detail. Are all 300 types completely independent? or are they are combinations of some lower level domain objects? Is there any commonality you could use?
    – JonasH
    Commented Oct 20, 2023 at 11:11

2 Answers 2

1

There is still another approach, which is to prefer composition over inheritance, and add the attributes dynamically as needed. Pseudo-code:

interface Component {
   componentName();
   getValue();
   setValue();  
}
 
class AbstractParentClass {
   commonAttribute1
   commonAttribute2
   commonBehavior1()
   addComponent(Component)
   getComponent(Name) 
   collection<Component> components
}

Of course, this design allows you create as many values as needed, without necessarily verifying consistency of the the attributes/components embedded individually. So some more thoughts are needed here.

If you push the thoughts to the extreme, you could even adopt the entity component system. This design pattern is popular in the gaming industry, because it avoids deep inflexible hierarchies and combinatorial explosion. The idea is then to have components that no longer represent a single attribute, but a group of attributes and/or behaviours.

1
  • Composition, when used in conjunction with toggleable attributes, tends to lead to a null-checking exercise where you will forever be checking if a particular component is present in the entity. That's not saying it can't or shouldn't be done, but doing so is not as clean or easy as it at first appears to be. It very much depends on what kind of reusability the OP is expecting from their shared class and whether or not this is actually easier than either inheritance or just a completely different approach.
    – Flater
    Commented Oct 23, 2023 at 4:27
-1

Based purely on the example you've given, I would suggest just using generics:

class EntityClass<T> {
  String commonParam1;
  String commonParam2;

  T typeParam1;
  T typeParam2;
}

The usage of it then becomes:

// ...

EntityClass<TypeA> typeAObject = new EntityClass<TypeA>();
EntityClass<TypeB> typeBObject = new EntityClass<TypeB>();

TypeA value1 = typeAObject.typeParam1;
TypeB valueB = typeBObject.typeParam1;

// ...

However as mentioned in the comments, depending on how you are using the entities, you may need to re-think the design.

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.