It seems unusual that you want to express this with an enumeration as opposed to inheritance. The thing with enumerations is that they're essentially compile-time constants, and if you wanted to generate more information in your hierarchy, you'd have to add more enumerations.
That can get messy, fast. It's also slightly contradictory to the real purpose of enumerations - as predefined constants instead of hierarchical entities.
What I propose is using an abstract class called CategoryBase
in which to draw everything out of. Then, create your inheritance tree based off of that.
Here's a diagram:

The bulk of the work is really holding properties, and we don't ever expect those properties to be changed once created, so we can allow our abstract class to hold them. We've also set them as final
, so they can't be modified, either.
public abstract class CategoryBase {
protected final int ranking;
protected final String name;
protected final SubCategory[] subCategories;
protected CategoryBase(int ranking, String name, SubCategory... subCategories) {
this.ranking = ranking;
this.name = name;
this.subCategories = subCategories;
}
public int getRanking() {
return ranking;
}
public String getName() {
return name;
}
public SubCategory[] getSubCategories() {
return subCategories;
}
}
From there, we can start basing our marker classes off of this - including SubCategory
, since it's really just a holder of information that's represented in a different way.
This would also make writing the marker classes straightforward and simple. For example, here's Camera
:
public class Camera extends CategoryBase {
protected Camera(int ranking, String name) {
super(ranking, name);
}
}
It's got a striking similarity to SubCategory
- a SubCategory
doesn't have any nested SubCategory
s, so we don't pass in anything to the vararg portion of the constructor.
For something that does have SubCategory
s, we need to instantiate them on construction. Here's SecuritySensor
as an example.
public class SecuritySensor extends CategoryBase {
public SecuritySensor(int ranking, String name) {
super(ranking, name,
new SubCategory(1, "Door Sensor"),
new SubCategory(2, "Leak Sensor"),
new SubCategory(3, "Motion Sensor"));
}
}
This approach gives you some flexibility around ranking as well - if you wanted to be able to specify the exact ranking of the subcategories at runtime, you'd replace this constructor with one that supported the vararg signature.