Sunday, December 19, 2010

Avoid switch! Use enum-2

In this case you don’t need the switch-case at all. Instead, you can tell the enum to do all the work:

01public enum Status {
02 INACTIVE {
03 public void doSomething() {
04 //do something
05 }
06 },
07 ACTIVE {
08 public void doSomething() {
09 //do something else
10 }
11 },
12 UNKNOWN {
13 public void doSomething() {
14 //do something totally different
15 }
16 };
17
18 public abstract void doSomething();
19}

The switch-case then shrinks to:

1getState().doSomething();

But what if the constants are defined by some third-party code? Let’s adapt the example above to match this scenario:

1public static final int INACTIVE = 0;
2public static final int ACTIVE = 1;
3public static final int UNKNOWN = 2;

Which would result in a switch-case very similar to the one above and again, you don’t need it. All you need to do is:

1Status.values()[getState()].doSomething();

Regarding this case there is a small stumbling block, which you have to pay attention to. Enum.values() returns an Array containing the elements in the order they are defined, so make sure that order accords to the one of the constants. Furthermore ensure that you do not run into an ArrayOutOfBoundsException. Hint: Time to add a test.

There is yet another case that may occur. Let’s pretend you encounter some constants that aren’t as nicely ordered as the ones above:

1public static final int INACTIVE = 4;
2public static final int ACTIVE = 7;
3public static final int UNKNOWN = 12;

To cover this case, you need to alter the enum to look something like:

01public enum Status {
02 INACTIVE(4),
03 ACTIVE(7),
04 UNKNOWN(12);
05
06 private int state;
07
08 public static Status getStatusFor(int desired) {
09 for (Status status : values()) {
10 if (desired == status.state) {
11 return status;
12 }
13 }
14 //perform error handling here
15 //e.g. throw an exception or return UNKNOWN
16 }
17}

Even though this introduces an if (uh oh, didn’t obey rule #4), it still looks much more appealing to me than a switch-case or if-else-cascade would. Hint: Time to add another test.

How do you feel about this technique? Got good or bad experiences using it?

No comments:

Post a Comment