我有ExecutorService
用于处理任务流。任务由我的DaemonTask
类表示,每个任务都构建一个响应对象,该对象被传递给响应调用(在此问题的范围之外)。我使用switch
语句根据任务ID int
生成相应的任务。它看起来像;
//in my api listening thread
executorService.submit(DaemonTask.buildTask(int taskID));
//daemon task class
public abstract class DaemonTask implements Runnable {
public static DaemonTask buildTask(int taskID) {
switch(taskID) {
case TASK_A_ID: return new WiggleTask();
case TASK_B_ID: return new WobbleTask();
// ...very long list ...
case TASK_ZZZ_ID: return new WaggleTask();
}
}
public void run() {
respond(execute());
}
public abstract Response execute();
}
<小时/> 我的所有任务类(例如
WiggleTask()
)extend DaemonTask
并提供execute()
方法的实现。
我的问题很简单;这种模式合理吗?当我看到我的巨大开关盒及其所有返回语句时,感觉有些不对劲。我试图以某种方式使用反射来提出一个更优雅的查找表解决方案,但似乎无法找到一种可行的方法。
答案 0 :(得分:1)
您可以使用enum
:
public enum TaskBuilder
{
// Task definitions
TASK_A_ID(1){
@Override
public DaemonTask newTask()
{
return new WiggleTask();
}
},
// etc
// Build lookup map
private static final Map<Integer, TaskBuilder> LOOKUP_MAP
= new HashMap<Integer, TaskBuilder>();
static {
for (final TaskBuilder builder: values())
LOOKUP_MAP.put(builder.taskID, builder);
}
private final int taskID;
public abstract DaemonTask newTask();
TaskBuilder(final int taskID)
{
this.taskID = taskID;
}
// Note: null needs to be handled somewhat
public static TaskBuilder fromTaskID(final int taskID)
{
return LOOKUP_MAP.get(taskID);
}
}
有了这样的枚举,你就可以这样做:
TaskBuilder.fromTaskID(taskID).newTask();
另一种可能性是使用构造函数字段而不是方法,即使用反射。编写起来要容易得多,而且工作正常,但异常处理就变成了噩梦:
private enum TaskBuilder
{
TASK_ID_A(1, WiggleTask.class),
// others
// Build lookup map
private static final Map<Integer, TaskBuilder> LOOKUP_MAP
= new HashMap<Integer, TaskBuilder>();
static {
for (final TaskBuilder builder: values())
LOOKUP_MAP.put(builder.taskID, builder);
}
private final int index;
private final Constructor<? extends DaemonTask> constructor;
TaskBuilder(final int index, final Class<? extends DaemonTask> c)
{
this.index = index;
// This can fail...
try {
constructor = c.getConstructor();
} catch (NoSuchMethodException e) {
throw new ExceptionInInitializerError(e);
}
}
// Ewww, three exceptions :(
public DaemonTask newTask()
throws IllegalAccessException, InvocationTargetException,
InstantiationException
{
return constructor.newInstance();
}
// Note: null needs to be handled somewhat
public static TaskBuilder fromTaskID(final int taskID)
{
return LOOKUP_MAP.get(taskID);
}
}
这个枚举可以和其他枚举一样使用。
答案 1 :(得分:1)
你真的需要这么多课吗?每个taskId可以有一个方法。
final ResponseHandler handler = ... // has many methods.
// use a map or array or enum to translate transIds into method names.
final Method method = handler.getClass().getMethod(taskArray[taskID]);
executorService.submit(new Callable<Void>() {
public Void call() throws Exception {
method.invoke(handler);
}
});
如果你必须有很多课程,你可以做
// use a map or array or enum to translate transIds into methods.
final Runnable runs = Class.forName(taskClassArray[taskID]).newInstance();
executorService.submit(new Callable<Void>() {
public Void call() throws Exception {
runs.run();
}
});