Using Java Enum for String-Based Dispatching
Thursday, December 17th, 2009
I ran across some (horrific) test code the other day that took this form:
public void testRunner(String toInvoke) {
...
SimpleTest test = ...;
if ("METHOD1".equals(toInvoke)) {
...
test.invoke_method1(...);
...
}
else if ("METHOD2".equals(toInvoke)) {
...
test.invoke_method2(...);
...
}
// and so on
}
There were probably 50 if/else blocks, occupying around 500 lines. Each block contained the exact same code, including try/catch exception handling, save for the actual method being invoked on the SimpleTest object. Essentially we’d like to be able to invoke a method based on the name of that method.
With a dynamic language like PHP, you can do a dynamic invocation easily:
$testObject = ...; $methodName = ...; $testObject->$methodName(...);
But you lose the benefits of a statically-typed language; it’s not until runtime that you find out whether the $methodName code actually exists.
So in Java you can clean up the if/else explosion by using an enum-based dispatch. You’ll need to know the strings in advance, but if you’re writing test cases that pass in strings, this is likely a non-issue anyway. Let’s set up an enum:
enum Dispatcher {
METHOD1 {
boolean invokeOn(Simple simple) {
return simple.returnTrue();
}
},
METHOD2 {
boolean invokeOn(Simple simple) {
return simple.returnFalse();
}
};
abstract boolean invokeOn(Simple simple);
}
Which then allows us to write a very simple handler for the string input:
boolean dispatch(String methodName) {
final Dispatcher d = Dispatcher.valueOf(methodName);
return d.invokeOn(new Simple());
}
Now you are freed from having a 1-to-1 correspondence between your string input and the actual method name to be invoked. You’ve shifted this to the enumeration. And since an enumeration is an actual Java construct, you’ve recouped the ability for static analysis, refactoring, etc.
Of course there are other ways to dispatch based on the String value of a method. Reflection allows you to do this explicitly, and may have been an equally good, if not better, solution to the enumeration. Regardless, when you find yourself writing 500 lines of if/else, alarms should be going off.
For continued good reading on dynamic dispatching, have a look at a couple of good posts over at Java Clippings.


