2012-06-29 112 views
0

我有枚举在JAVA代码ERequestTypes我的枚举包含多于20个元素,每个元素都是我的JAVA代码中的函数的名称。现在我想要做下列的东西,而不是写switch(ERequestTypes) case,并在案件以这种方式调用函数:来自枚举的调用函数

switch(ERequestTypes a) { 
    case ERequestTypes.Initialize: 
     Initialize(); 
    case ERequestTypes.Uninitialize: 
     Uninitialize(); 
} 

我想用一条线来做到这一点。枚举中的所有函数具有相同的参数并返回相同的int值。我该怎么做?可能会像C++或其他东西一样保留enum中的函数指针。请帮忙 !

class CRequestValue { 
    /** 
    * Constructor. 
    * 
    * @param aName - Name of the request. 
    * @param aCode - Code of the request. 
    */ 
    public CRequestValue(String aName, int aCode) { 
     this.mName = aName; 
     this.mCode = aCode; 
    } 

    private String mName; 
    private int mCode; 

    public String GetName() { 
     return this.mName; 
    } 

    public int GetCode() { 
     return this.mCode; 
    } 

} /* class CRequestValue **/ 

enum ERequestTypes 
{ 
    Initialize(new CRequestValue("Initialize", 0)), 
    Uninitialize(new CRequestValue("Uninitialize", 1)), 
    GetDeviceInfoList(new CRequestValue("GetDeviceInfoList", 2)), 
    GetDeviceInfo(new CRequestValue("GetDeviceInfo", 3)); 

    private CRequestValue mRequestValue; 

    private ERequestTypes(CRequestValue aRequestValue) { 
     this.mRequestValue = aRequestValue; 
    } 

    public String GetName() { 
     return this.mRequestValue.GetName(); 
    } 

    public int GetCode() { 
     return this.mRequestValue.GetCode(); 
    } 

} /* enum ERequestTypes **/ 
+0

为什么要在枚举中安排函数?设计模式的目标是什么? –

+0

Java,而不是JAVA。 – missingfaktor

回答

2

您正在寻找reflection

ErequestTypes a = <init>; 
Object o = Class.forName(<your class name>).getMethod(a.getName(), <argtype>.class).invoke(<instance of your class, or null if static method>, <arg>); 

注意,调用Class.forName不需要,如果你已经知道的方法是什么类。

3

我不知道什么是你的目标,但你可以使用polimorphism代替开关块,例如:

interface Invokable { 
    int init(Object arg); 
    int uninit(Object arg); 
} 

enum Request { 
    INIT() { 
     @Override 
     public int invoke(Invokable invokable, Object arg) { 
      return invokable.init(arg); 
     } 
    }, 
    UNINIT() { 
     @Override 
     public int invoke(Invokable invokable, Object arg) { 
      return invokable.uninit(arg); 
     } 
    }, 
    ; 
    public abstract int invoke(Invokable invokable, Object arg); 
} 


Invokable i = ....; 
Object arg = ....; 
Request r = Request.INIT; 
r.invoke(i, arg); // should invoke Invokable.init(arg); 
r = Request.UNINIT; 
r.invoke(i, arg); // should invoke Invokable.uninit(arg); 
0

你可以用Pavel提到的多态性,但还有另一种解决方案 - 你根本不需要枚举。

让每个函数都是自己的对象,并且像使用枚举本身一样传递/使用这些对象的实例是非常简单的。

还有一些解决方案使用匿名内部类(将它们附加到对象实例并传递这些实例),但我认为这通常不像可单独创建对象那样可重用。

下面是一些假代码:

public void MainClass { 
    private final Runnable init=new Runnable { 
     run() { 
      // Initialize the system 
     } 
    } 
    private final Runnable uninit = new Runnable() { 
     run() { 
      // Uninitialize the system 
     } 
    } 

public someMethod() { 

    // At this point you can treat the instances as you would any variable... 
    Runnable nextOperation = init; 

    // and executing whichever one you have is as simple as: 
    nextOperation.run(); 

如果您想为“安全型”(如枚举)不延长Runnable的,但创建一个扩展可运行然后扩展该类的新类。由于这些是“内部类”(定义在另一个类的上下文中),因此它们可以访问和修改所有类成员变量,使得它们更像是独立类,而不像独立类。

最后要注意的是,由于每个类都是匿名定义的,它们几乎与枚举一样很难创建“Duplicates”,所以通常可以将它们完全视为枚举(例如,使用“==”而不是。等于()