First Implementation
public enum ReviewFlowExample {
Draft {
@Override
public ReviewFlowExample getNext() {
return Review;
}
@Override
public ReviewFlowExample getPrevious() {
return null;
}
},
Review {
@Override
public ReviewFlowExample getNext() {
return Final;
}
@Override
public ReviewFlowExample getPrevious() {
return Draft;
}
},
Final {
@Override
public ReviewFlowExample getNext() {
return null;
}
@Override
public ReviewFlowExample getPrevious() {
return Review;
}
};
public abstract ReviewFlowExample getNext();
public abstract ReviewFlowExample getPrevious();
public boolean isDraft() {
return this.equals(Draft);
}
}
Second Implemenation
public enum ReviewFlowExample {
Draft,
Review,
Final;
private ReviewFlowExample next;
private ReviewFlowExample previous;
static{
Draft.setNext(Review);
Review.setNext(Final);
Review.setPrevious(Draft);
Final.setPrevious(Review);
}
private ReviewFlowExample(){
}
public ReviewFlowExample getNext(){
return next;
}
public ReviewFlowExample getPrevious(){
return previous;
}
private void setNext(ReviewFlowExample next){
this.next = next;
}
private void setPrevious(ReviewFlowExample previous){
this.previous = previous;
}
public boolean isDraft(){
return this == Draft;
}
}
3 Answers 3
Why not use the order you are setting up in the enum declaration? I played with this a while ago and came up with something like this (modified to fit your implementation above):
private enum Planet { MERCURY, VENUS, EARTH, MARS, JUPITER, SATURN, URANUS, NEPTUNE;
public Planet getNext() {
return this.ordinal() < Planet.values().length - 1
? Planet.values()[this.ordinal() + 1]
: this;
}
public Planet getPrevious() {
return this.ordinal() > 0
? Planet.values()[this.ordinal() - 1]
: this;
}
-
\$\begingroup\$ You can find the original in my blog post at digitaljoel.nerd-herders.com/2011/04/05/… but there's not much more info there than you'll find here. \$\endgroup\$digitaljoel– digitaljoel2011年11月24日 04:33:06 +00:00Commented Nov 24, 2011 at 4:33
Just to spice up the discussion, you could also do something like this:
public ReviewFlowExample getNext() {
ReviewFlowExample[] values = values();
int next = ordinal() + 1 == values.length ? ordinal() : ordinal() + 1;
return values[next];
}
-
\$\begingroup\$ is this dependent on the order of appearance. \$\endgroup\$Shahzeb– Shahzeb2011年11月24日 04:45:40 +00:00Commented Nov 24, 2011 at 4:45
-
\$\begingroup\$ You bet :) Luckily tests can confirm order! \$\endgroup\$Muel– Muel2011年11月24日 04:48:49 +00:00Commented Nov 24, 2011 at 4:48
-
1\$\begingroup\$ Saw your comment below (I don't have general comment privileges yet). Please tell me your employer doesn't enforce alphabetical order of members!? We use IDEs for a reason! \$\endgroup\$Muel– Muel2011年11月24日 04:50:59 +00:00Commented Nov 24, 2011 at 4:50
-
1\$\begingroup\$ @Muel Two jobs ago they had Jalopy set up to alphabetize properties and methods as a CVS checkin hook. It drove me insane--it essentially randomized the class. It took quite awhile before I was allowed to remove the hook :( \$\endgroup\$Dave Newton– Dave Newton2011年11月26日 03:25:24 +00:00Commented Nov 26, 2011 at 3:25
Although the other answers are correct, their readability suffers and they work only for linear workflows (and I don't like solutions which rely on declaration). I would go for readability, which is better in the second implementation. But it could be shortend:
public enum ReviewFlowExample {
Draft,
Review,
Final;
private ReviewFlowExample next = null;
private ReviewFlowExample previous = null;
static{
Draft.next = Review;
Review.previous = Draft;
Review.next = Final;
Final.previous = Review;
}
public ReviewFlowExample getNext(){
return next;
}
public ReviewFlowExample getPrevious(){
return previous;
}
public boolean isDraft(){
return this == Draft;
}
}
Peter suggested using a state machine instead. I think the first solution is already a state machine, there is no need to add extra interfaces. You just have to move your workflow logic into the enum. But it's hard to tell, if a state machine is worth it, without knowing the other code.
getNextState()
and so on)? \$\endgroup\$null
as it is in the second example. \$\endgroup\$