如何在不使用“if-else if”的情况下编写对不同参数使用不同方法的代码?

时间:2014-03-28 05:41:39

标签: java design-patterns

对我而言,if - else if太长而且难以阅读。

我是否可以使用一些表驱动方法来映射输入值以调用该值的特定方法?

例如:

for(String id:ids){

    Test test = new Test();

    if(id == "101") {    
        test.method1();
    }else if(id=="102") {
        test.method2();
    }else if(id=="103"){
        test.method3();
     ...

3 个答案:

答案 0 :(得分:2)

...
static Map<String,Method> methods = new HashMap<String,Method>();
...
static {
    methods.put("101",Test.class.getMethod("method1",null));
    methods.put("102",Test.class.getMethod("method2",null));
    ...
}
...
for( String id : ids ) {
    Test test = new Test();
    Method m = methods.get(id);
    if (m != null) {
        m.invoke(test,null);
    }
}

当然,所有这一切确实是交易if / else链的痛苦,因为用所有方法初始化哈希的痛苦。

答案 1 :(得分:1)

您可以使用反射来调用方法。从字符串构造方法名称并从java.lang.reflect命名空间使用方法类来调用方法并传递参数。 像这样的东西

Method theMethod = yourClass.getClass().getMethod("methodName", null);
method.invoke(yourClass, );

答案 2 :(得分:1)

实际上,你的代码不太正确,因为它使用==来检查字符串的相等性。

您应该使用equals方法:

for(String id: ids){

    Test test = new Test();

    if(id.equals("101")) {
        test.method1();
    }else if(id.equals("102")) {
        test.method2();
    }else if(id.equals("102")){
        test.method3();
    // etc.
    }
}

其他答案建议创建方法地图Map<String,Method>并使用反射。这将起作用,可能对您的使用完全合理,但会丢失一些编译时类型的安全检查。

您可以通过定义接口并使用该接口的实例填充地图来获取这些检查:

interface TestMethod {
   void  execute(Test test);
}

private static HashMap<String, TestMethod> methodMap = new HashMap<String, TestMethod>();

static {
    methodMap.put("101", new TestMethod(){
        @Override
        public void execute(Test test) {
            test.method1();
        }
    });
    methodMap.put("102", new TestMethod(){
        @Override
        public void execute(Test test) {
            test.method2();
        }
    });
    methodMap.put("103", new TestMethod() {
        @Override
        public void execute(Test test) {
            test.method3();
        }
    });
    // etc.
}

然后你的循环可以编码为

for (String id: ids) {
    Test test = new Test();
    methodMap.get(id).execute(test);
}

就像在这里一样,不幸的是,这使代码更长,并且至少至少难以阅读。但是如果您使用的是Java 8,则可以使用lambda expressions填充地图,这会使静态初始化程序块看起来更像:

static {
    methodMap.put("101", t -> t.method1();
    methodMap.put("102", t -> t.method2();
    methodMap.put("103", t -> t.method3();
    // etc.
}

然后它可能真的值得做。

但是,如果这种基于某种字符串“代码”的条件在您的应用程序中很常见,并且特别是如果您有多个条件取决于相同的代码,您可能需要更多更广泛的重新设计,以封装为类层次结构中的不同代码所执行的不同操作,并使用多态而不是if-else(或switch)或方法映射查找。您仍然可能需要一些条件来构建类的实例,但代码可能会有很大的改进。