当前,我有一堆实现Processor接口的Java类,这意味着它们都具有processRequest(String key)方法。这个想法是,每个类都有几个(例如<10)成员Strings,并且每个成员都通过processRequest方法映射到该类中的方法,如下所示:
class FooProcessor implements Processor
{
String key1 ="abc";
String key2 ="def";
String key3 ="ghi";
// and so on...
String processRequest(String key)
{
String toReturn = null;
if (key1.equals(key)) toReturn = method1();
else if (key2.equals(key)) toReturn = method2();
else if (key3.equals(key)) toReturn = method3();
// and so on...
return toReturn;
}
String method1() { // do stuff }
String method2() { // do other stuff }
String method3() { // do other other stuff }
// and so on...
}
你明白了。
这对我来说很好,但是现在我需要一个从键到函数的运行时可访问的映射。并非每个函数实际上都返回一个String(有些返回void),并且我需要动态地访问每个具有键的类中每个函数的返回类型(使用反射)。我已经有一位经理,他了解所有键,但是不知道从键到功能的映射。
我的第一个直觉是用Map替换使用if-else语句的此映射,就像我在Javascript中所做的那样。但是,Java不支持一流的功能,因此我很不走运。我可能会挖掘出一个第三方库,该库可以让我使用一流的功能,但是还没有看到,我怀疑是否需要一个全新的库。
我还考虑过将这些String键放入数组中,并使用反射按名称调用方法,但是我看到此方法有两个缺点:
我的键名必须与方法相同-或以特定,一致的方式命名,以便轻松将它们映射到方法名。
这似乎比我现在使用的if-else语句要慢。效率是一个令人担忧的问题,因为这些方法将经常被频繁调用,并且我想将不必要的开销降至最低。
TL; DR:我正在寻找一种干净,开销最小的方法来将String映射到某种我可以调用和调用(例如)getReturnType()的Function对象。如果真的适合我的需求,我不介意使用第三方库。我也不介意使用反射,尽管我强烈希望避免每次执行方法查找时都使用反射-也许使用一些结合了Map和反射的缓存策略。
对获得我想要的好方法的想法?干杯!
您是否可以将字符串转换为方法(java.sun.com/j2se/1.4.2/docs/api/java/lang/reflect/Method.html)? 然后,您可以缓存需要执行的方法。
@Chris-是的,这基本上就是我在问题末尾要去的地方。
完成了 :) :) :)
没有任何一流的独立功能,但是您可以使用界面来完成所需的操作。创建一个代表您的功能的接口。例如,您可能具有以下内容:
public interface ComputeString
{
public String invoke();
}
然后,您可以首先创建所需的Map对象。使用地图将比反射快得多,并且还将提供更多的类型安全性,因此我建议您这样做。
那将意味着为我要调用的每个单个函数都具有一个实现类,这似乎很笨拙,并且每个单个函数都需要一些样板。听起来对我来说很棒。
它完全笨拙,但是那是Java的错,因为它不直接支持高阶函数。
@Bears,是的,它很笨重,但是您可以构造匿名类,这应该使它不那么笨重,例如map.put(str,new ComputeString(){public String invoke(){return" blah";}});
虽然您没有一流的功能,但是有一些匿名类可以基于接口:
interface ProcessingMethod {
String method();
}
Map methodMap = new HashMap();
methodMap.put("abc", new ProcessingMethod() {
String method() { return"xyz" }
});
methodMap.put("def", new ProcessingMethod() {
String method() { return"uvw" }
});
methodMap.get("abc").method();
或者您可以使用Scala :-)
您不能对Method做String吗?然后,您可以缓存需要执行的方法。
本示例使用命名函数的enum和抽象的FunctionAdapter来调用具有可变数量的同类参数的函数,而不进行反射。 lookup()函数仅使用Enum.valueOf,但是Map对于大量函数可能值得。
反射API的Method类呢?您可以根据名称,参数或返回类型找到类的方法。然后,您只需调用Method.invoke(this,parameters)。
这与您正在谈论的JavaScript中的Map几乎相同。
使用Map,其中键是一个字符串,值是一个实现包含method()的接口的对象。这样,您可以从地图中获取包含所需方法的对象。然后只需在对象上调用该方法。例如:
class FooProcessor implements Processor{
Map myMap;
String processRequest(String key){
FooMethod aMethod = myMap.getValue(key);
return aMethod.method();
}
}
如您所见,您可以使用Reflection API进行所需的操作,但是除了已经提出的问题之外,还失去了Java编译器的一些优势。将您的字符串包装在一个对象中并使用Visitor模式可以解决您的问题吗?每个StringWrapper仅接受具有正确方法或类似内容的Visitor。
我不认为"访客"模式在这里是正确的方法-也就是说,我没有出售它。 Visitor可以做什么?手术将是什么?
@Bears会吃掉你-当我想到这个主意时,我为访客描绘了一个访问每个String的包装器的场景,但是看起来您不知道什么时候出现String。我认为接口的想法要简单得多。
游客?使用命令或策略模式。其他答案演示了命令模式。您可以在这里找到现实生活中的模式示例,以便对它们有所了解。