Java中函数映射的等效实现
在Python中,如果我有几个函数想要根据输入来调用,我可以这样做:
lookup = {'function1':function1, 'function2':function2, 'function3':function3}
lookup[input]()
也就是说,我有一个字典,这个字典把函数的名字和函数本身对应起来,然后通过查这个字典来调用函数。
那么在Java中怎么做呢?
7 个回答
2
你可以使用一个叫做Map的东西,比如Map<String,Method>或者Map<String,Callable>,然后用map.get("function1").invoke(...)来调用函数。但是通常情况下,这种问题用多态的方法会更简单、更干净,而不是通过查找来解决。
16
Java没有一等公民的方法,所以你可以使用命令模式来解决这个问题...
注意:代码没有经过测试!
public interface Command
{
void invoke();
}
Map<String, Command> commands = new HashMap<String, Command>();
commands.put("function1", new Command()
{
public void invoke() { System.out.println("hello world"); }
});
commands.get("function1").invoke();
4
解决这个问题有几种方法。大部分方法已经有人提过了:
- 命令模式 - 可以把一堆有 execute() 或 invoke() 方法的对象放在一个映射中;通过名字查找命令,然后调用这个方法。
- 多态 - 更广泛地说,你可以在任何相关的对象集合上调用方法。
- 最后是反射 - 你可以使用反射来获取 java.lang.Method 对象的引用。对于一组已知的类和方法,这种方式效果不错,而且一旦加载了 Method 对象,开销也不大。比如,你可以让用户在命令行中输入 Java 代码,然后实时执行。
个人来说,我会选择命令模式。命令模式和模板方法结合得很好,可以在所有命令对象上强制执行某些模式。举个例子:
public abstract class Command {
public final Object execute(Map<String, Object> args) {
// do permission checking here or transaction management
Object retval = doExecute(args);
// do logging, cleanup, caching, etc here
return retval;
}
// subclasses override this to do the real work
protected abstract Object doExecute(Map<String, Object> args);
}
我只会在需要对你无法控制设计的类进行这种映射时才使用反射,这种情况下做命令不太实际。例如,你不能通过为每个方法创建命令来在命令行中暴露 Java API。