I'm working on a framework in which we have the concept of a task. The hope is that lots of people will write tasks, and to do so they will simply need to implement the Task interface. The tasks need to be triggered via their name, meaning there needs to be a central registry of task-name->task-class somewhere. Currently I'm using an Enum to do this, but this requires task implementers to add code into the Enum for every task they implement, which is gross.
Another option I've come up with is to search via reflection for all classes that implement the Task interface and register them from there. This also strikes me as gross and I feel there must be a better way.
A static initializer would be perfect if it didn't require the class be referenced at least once before it ran.
Annotations are another option, but they require either more reflection work, or changing the build process if we were to do compile time code-gen to make the dispatcher.
Any simpler ideas?
A simple version of what I'm doing now is below, to give an idea of the control flow I want (smashed into a single class for simplicity):
class Disp {
interface Task {
public String doTask();
}
static class HelloTask implements Task {
public String doTask() {
return "Hello";
}
}
static class ByeTask implements Task {
public String doTask() {
return "Bye";
}
}
static class TaskDispatcher {
static enum Tasks {
Hello {
Task getTask() {
return new HelloTask();
}
},
Bye {
Task getTask() {
return new ByeTask();
}
};
abstract Task getTask();
};
public static Task getTask(String taskName) {
return Tasks.valueOf(taskName).getTask();
}
}
public static void main(String[] args) {
System.out.println("Hello task says: "+TaskDispatcher.getTask("Hello").doTask());
System.out.println("Bye task says: "+TaskDispatcher.getTask("Bye").doTask());
}
}
What would be much nicer is if the code to register (say) HelloTask could live only inside HelloTask and not have to leak out into TaskDispatcher (As in the real project these are multiple different files)