I am implementing a state machine in enum in Java. I have a toy example below, where I transition between X
,Y
and Z
states based on group membership.
The issue is, the transition rule for Y
and Z
are identical (i.e., the Overriden methods are identical).
Is there any way to avoid code duplication here? In my real life example, it is a bit more severe so the code duplication potential is worse.
enum Group {
A,B,C
}
enum Element {
X(Group.A) {
@Override
public Element getNextElement(Element nextElement) {
if(nextElement.getGroup() == Group.B) {
return nextElement;
} else {
return this;
}
}
},
Y(Group.B) {
@Override
public Element getNextElement(Element nextElement) {
if(nextElement.getGroup() == Group.A) {
return nextElement;
} else {
return this;
}
}
},
Z(Group.C) {
@Override
public Element getNextElement(Element nextElement) {
if(nextElement.getGroup() == Group.A) {
return nextElement;
} else {
return this;
}
}
};
Group group;
Element(Group group) {
this.group=group;
};
public Group getGroup() {
return this.group;
}
public abstract Element getNextElement(Element nextElement);
}
Given that your logic is identical except for the value in the transition rule, you can just parameterize by that:
enum Element {
X(Group.A, Group.B),
Y(Group.B, Group.A),
Z(Group.C, Group.A);
private final Group group;
private final Group nextGroup
private Element(Group group, Group nextGroup) {
this.group = group;
this.nextGroup = nextGroup;
}
public Group getGroup() {
return this.group;
}
public Element getNextElement(Element nextElement) {
return nextElement.getGroup() == nextGroup ? nextElement : this;
}
}
You can still override getNextElement
in some values. For example:
enum Element {
X(Group.A, Group.B) {
@Override public Element getNextElement(Element nextElement) {
return someRandomCondition ? nextElement : this;
}
}
Y(Group.B, Group.A),
Z(Group.C, Group.A);
// Other code as above
}
See more on this question at Stackoverflow