2011-09-14 49 views
4

是否可以用反射來創建一個動態的IF語句?如何創建動態的IF語句?反射?

我看過BeanShell的例子(像這樣:Dynamic if statement evaluation problem with string comparison),但我想知道是否有可能在沒有BeanShell的情況下做到這一點,並指出一些例子以適應我的需求。

基本上我有以下形式的語句:甲運營商B

A和B可以是數字(雙打或整數)或字符串,但總是A是相同的類型B. 操作者可以! =,==,> =,>,< =,<,甚至其他的行爲可以通過他們自己的類來定義,另一個原因爲什麼我會使用反射,因爲我可以接受該字符串並使用反射來調用適當的方法。

我想(必須)避免分支「如果」和「切換」,因爲變化太多,並會隨用戶生成的輸入不斷變化。

+4

你爲什麼要這麼做?爲什麼不使用策略設計模式? – Raedwald

+2

無論你在做什麼,動態創建IF都不是這種方式 – Steve

+0

我從字面上通過自定義腳本語言閱讀條件。它們的形式如下:functionA operator functionB。運營商現在有限,但可能增長。我希望能夠閱讀字符串,並以某種方式評估表達式。 – rciafardone

回答

1

反思無濟於事。反射爲您提供有關您的代碼結構(類,方法,屬性)的信息,但它不允許您更改和更新現有代碼。

不要嘗試生成新的代碼,而是嘗試添加一種方式讓用戶根據自己的輸入更改應用程序的行爲。

我不確切地知道你在做什麼。發佈一些用戶輸入和預期行爲的示例,以幫助縮小選項範圍。但這裏的幾件事情,可以幫助你在你的任務:

  • 有一個用戶界面,幫助用戶選擇操作數的時間,與值文本字段,併爲運營商一個下拉框。簡單的解決方案,但我不會推薦它,因爲它可能會增加用戶界面的複雜性。
  • 爲您的表達式編寫解析器。爲這個非常簡單的語言(A運算符B)寫一個簡單的解析器應該在合理的時間內可行。
  • 域特定語言。允許應用程序的用戶編寫一些腳本,這些腳本可以被應用程序解釋並以某種方式作出響應。你可以想象一個簡單比較的DSL,結果會影響你的應用程序的行爲。看看Groovy,這是一個很好的用例。
+0

謝謝。其他人都誤解了我想實現的目標,因爲他們只是給出了我想要避免的版本:自己對操作員進行硬編碼。我想知道是否有一種方法可以從腳本語言中使用適當的java語法創建字符串並評估該表達式,就像在本文中使用BeanShell一樣:http://stackoverflow.com/questions/2838801/dynamic-if-聲明評價,問題與 - 字符串比較。問題是BeanShell接縫死了,我不想把它添加到我的項目中。實際上你的第一點和第二點已經是我的程序的一部分了:P – rciafardone

+0

反思部分是因爲在BeanShell中,我連接它們使用它,我自己用它來調用apropiate方法的一部分,這取決於什麼腳本語言說。示例:Count(a.value,set)> = value(4)。 Count只需查找set中存在多少個a.value並返回一個數字。使用反射我解析腳本文件後調用適當的方法。 – rciafardone

1

你可以做這樣的

public interface MyComparator 
{ 
    public boolean matches(String operator); 
    public boolean compare(String a, String b); 
} 

一個接口,那麼你可以讓你想要多少班都實行這樣的

public class MyEquals implements MyComparator 
{ 
    @Override 
    public boolean matches(String operator) 
    { 
    return "==".equals(operator); 
    } 

    @Override 
    public boolean compare(String a, String b) 
    { 
    return a.equals(b); 
    } 
} 

接口並加載它們像這樣:

Class compClass = Class.forName(classname); 
MyComparator comp = (MyComparator)compClass.newInstance(); 

你可以這樣準備一個所有可用的操作符的列表並迭代它, n具有在屬性文件上配置的運算符列表。

+0

問題在於它暗示了對運算符進行硬編碼,這與爲每個我想要的情況創建一個大開關(運算符)幾乎相同。我甚至有一個類運算符,每個運算符都有一個int ID,但我正在尋找更靈活的解決方案。 – rciafardone

+0

誰會定義運營商行爲?你(程序員)還是用戶? – Maxx

+0

\ @Maxx:很好的問題,第一批函數將由我(程序員)定義,但是我想讓用戶開放以擴展我創建的函數類並添加它們自己的函數。在功能上,他們編寫類,他們添加配置文件的名稱,並可以使用該新函數創建條件。但我想我會改變規格,減少雄心,我的時間不多了。 – rciafardone

3

您可以創建一個工廠,爲給定輸入返回正確的運算符。

public class OperatorFactory { 
    private static final Map<String, Operator<?>> OPERATORS = new HashMap<String, Operator<?>>(); 

    static { 
    OPERATORS.put("<Number", new LessThanNumOperator()); 
    OPERATORS.put("==Number", new EqualToNumOperator()); 
    OPERATORS.put("<String", new LessThanStringOperator()); 
    ... 
    } 

    public static Operator<?> getOperator(String someUserSpecifiedOp, Class<?> paramType) { 
    String key = someUserSpecifiedOp; 
    if (Number.class.isAssignableFrom(paramType)) { 
     key += "Number"; 
    } else if (String.class.isAssignableFrom(paramType)) { 
     key += "String"; 
    } 
    return OPERATORS.get(key); 
    } 
} 

public interface Operator<T> { 
    public boolean execute(T lhs, T rhs); 
} 

public class LessThanNumOperator implements Operator<Number> { 
    public boolean execute(Number lhs, Number rhs) { 
    return lhs.doubleValue() < rhs.doubleValue(); 
    } 
} 

,然後使用它:

OperatorFactory.getOperator(userDesignatedOperation, lhs.getClass()).execute(lhs, rhs); 
+0

請注意,這是使用工廠和策略設計模式。 –