2010-04-30 151 views
10

目前,我有一堆實現Processor接口的Java類,這意味着它們都有一個processRequest(String key)方法。我們的想法是,每個班有幾個(比如,< 10)成員Strings,而且每個映射到該類中的方法通過processRequest方法,像這樣:如何將字符串映射到Java中的函數?

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... 
} 

你的想法。

這對我來說工作得很好,但現在我需要一個從鍵到功能的運行時可訪問映射;不是每個函數實際上返回一個字符串(一些返回void),我需要動態訪問每個類中每個函數的返回類型(使用反射),有一個鍵。我已經有一位知道所有密鑰的管理員,但是不是從鍵到功能的映射。

我的第一個直覺是用if-else聲明替換這個映射,Map<String, Function>,就像我在Javascript中可以做的那樣。但是,Java不支持一流的功能,所以我在那裏運氣不好。我可能會挖掘一個第三方庫,它可以讓我使用一流的功能,但是我還沒有看到,我懷疑我需要一個全新的庫。

我也想過把這些String鍵到一個數組中,並使用反射來調用的名字方法,但我看到兩個缺點這種方法:

  • 我的鑰匙就必須命名一樣該方法 - 或以特定的一致方式命名,以便將它們映射到方法名稱很容易。
  • 這似乎比我現在所說的if-else陳述慢。效率是一個值得關注的問題,因爲這些方法往往會被頻繁調用,並且我想盡量減少不必要的開銷。

TL; DR:我正在尋找一種乾淨的架空最低限度的方式來將String映射到某種Function對象上,我可以調用它(類似於)getReturnType()。我不特別介意使用第三方庫,如果它真的符合我的需求。我也不介意使用反射,儘管我強烈希望避免每次使用反射時進行方法查找 - 也許使用一些將Map與反射相結合的緩存策略。

想得到我想要的東西嗎?乾杯!

+2

難道你不能做字符串方法(http://java.sun.com/j2se/1.4.2/docs/api/java/lang/reflect/Method.html)嗎?然後你可以緩存你需要執行的方法。 – 2010-04-30 15:53:21

+0

@Chris - 是的,那基本上就是我在問題結束時的標題。 – 2010-04-30 16:18:05

+0

完成它:) :) :) – 2011-03-25 05:43:22

回答

1

難道你不能做StringMethod?然後你可以緩存你需要執行的方法。

0

正如你已經注意到,你可以做你想做使用Reflection API什麼,但你失去了Java編譯器的一些好處,對你已經想出問題上面。將你的字符串包裝在一個對象中,並使用Visitor pattern解決你的問題?每個StringWrapper只接受一個Visitor有正確的方法,或類似的規定。

+0

我不認爲訪客模式是正確的方法在這裏 - 也就是說,我不賣它。 「訪客」會在哪些方面運作?該手術會是什麼? – 2010-04-30 16:20:21

+0

@熊會吃你 - 當我想到這個想法時,我想象訪問者訪問每個字符串的包裝,但是看起來你不知道什麼時候會出現字符串。我在想接口的想法簡單得多。 – justkt 2010-04-30 16:24:59

+3

訪客?使用命令或策略模式。其他答案演示了命令模式。你可以在這裏找到現實生活中的模式例子(這裏是http://stackoverflow.com/questions/1673841/examples-of-gof-design-patterns/2707195#2707195),這樣你可以更多地瞭解它們。 – BalusC 2010-05-01 03:14:04

7

沒有任何一流的獨立功能,但您可以使用界面進行任何操作。創建一個代表你的功能的界面。例如,你可能有以下幾點:

public interface ComputeString 
{ 
    public String invoke(); 
} 

然後,像你在第一個地方想你可以創建一個Map<String,ComputeString>對象。使用地圖會比反射速度快得多,並且還會提供更多類型安全性,所以我會建議上述內容。

+3

這意味着我要調用每個函數的實現類,這看起來很笨重,並且需要爲每個函數提供一些樣板。聽起來對我來說不好聽。 – 2010-04-30 16:31:14

+1

它完全笨拙,但這是Java的錯誤,因爲它不直接支持高階函數。 – 2010-04-30 21:41:39

+0

@熊,是的,它是笨重的,但你可以構造匿名類,這應該使它不那麼笨,就像map.put(str,new ComputeString(){public String invoke(){return「blah」;}}) ; – 2010-05-02 02:33:07

4

雖然你不能有一流的功能外,還有可基於接口的匿名類:

interface ProcessingMethod { 
    String method(); 
} 

Map<String, ProcessingMethod> methodMap = new HashMap<String, ProcessingMethod>(); 
methodMap.put("abc", new ProcessingMethod() { 
    String method() { return "xyz" } 
}); 
methodMap.put("def", new ProcessingMethod() { 
    String method() { return "uvw" } 
}); 

methodMap.get("abc").method(); 

或者你可以使用Scala的:-)

0

使用地圖的地方key是一個字符串,值是實現包含method()的接口的對象。這樣你就可以從地圖中獲取包含你想要的方法的對象。然後在對象上調用該方法。例如:

class FooProcessor implements Processor{ 

    Map<String, FooMethod> myMap; 

    String processRequest(String key){ 
     FooMethod aMethod = myMap.getValue(key); 
     return aMethod.method(); 
    }   
} 
0

example使用的命名的函數的enum和一個抽象FunctionAdapter具有均勻參數的無反射可變數量來調用功能。 lookup()功能只是使用Enum.valueOf,但Map可能適用於大量功能。

0

怎麼樣Method類從反射API?您可以根據名稱,參數或返回類型查找類的方法。然後你只需調用Method.invoke(this,parameters)。

這與您正在談論的來自JavaScript的地圖非常相似。

相關問題