如何避免许多if-else有很多条件

时间:2013-10-24 18:23:13

标签: java algorithm java-ee

我需要一些帮助来设计问题的逻辑。

模型Bean

package com.ashish.model;
public class Model {
    public Integer a,b,c,d;
    public String f,g,h,i,j;
}

服务类

package com.ashish.service;

import com.ashish.model.Model;
public class Service {
    public StringBuilder query = null;  
    public Service(){
        query = new StringBuilder("Select * from A where ");
    }
    public String build(Model m){
            if(m.a != null&&m.b==null&&m.c==null&&m.d==null&m.e==null&&m.f==null&&m.g==null&&m.h==null&&m.i==null&&m.j==null)
        query.append("a="+m.a);
    if(m.a == null&&m.b!=null&&m.c==null&&m.d==null&m.e==null&&m.f==null&&m.g==null&&m.h==null&&m.i==null&&m.j==null)
        query.append("b="+m.b);
    if(m.a == null&&m.b==null&&m.c!=null&&m.d==null&m.e==null&&m.f==null&&m.g==null&&m.h==null&&m.i==null&&m.j==null)
        query.append("c="+m.c);
    if(m.a == null&&m.b==null&&m.c==null&&m.d!=null&m.e==null&&m.f==null&&m.g==null&&m.h==null&&m.i==null&&m.j==null)
        query.append("d="+m.d);
    if(m.a == null&&m.b==null&&m.c==null&&m.d==null&m.e!=null&&m.f==null&&m.g==null&&m.h==null&&m.i==null&&m.j==null)
        query.append("e="+m.e);
    if(m.a == null&&m.b==null&&m.c==null&&m.d==null&m.e==null&&m.f!=null&&m.g==null&&m.h==null&&m.i==null&&m.j==null)
        query.append("f="+m.f);
    if(m.a == null&&m.b==null&&m.c==null&&m.d==null&m.e==null&&m.f==null&&m.g!=null&&m.h==null&&m.i==null&&m.j==null)
        query.append("g="+m.g);
    if(m.a == null&&m.b==null&&m.c==null&&m.d==null&m.e==null&&m.f==null&&m.g==null&&m.h!=null&&m.i==null&&m.j==null)
        query.append("h="+m.h);
    if(m.a == null&&m.b==null&&m.c==null&&m.d==null&m.e==null&&m.f==null&&m.g==null&&m.h==null&&m.i!=null&&m.j==null)
        query.append("i="+m.i);
    if(m.a == null&&m.b==null&&m.c==null&&m.d==null&m.e==null&&m.f==null&&m.g==null&&m.h==null&&m.i==null&&m.j!=null)
        query.append("j="+m.j);
    if(m.a != null&&m.b!=null&&m.c==null&&m.d==null&m.e==null&&m.f==null&&m.g==null&&m.h==null&&m.i==null&&m.j==null)
        query.append("a="+m.a);query.append(" b="+m.b);
    if(m.a != null&&m.b==null&&m.c!=null&&m.d==null&m.e==null&&m.f==null&&m.g==null&&m.h==null&&m.i==null&&m.j==null)
        query.append("a="+m.a);query.append(" c="+m.c);
    if(m.a != null&&m.b==null&&m.c==null&&m.d!=null&m.e==null&&m.f==null&&m.g==null&&m.h==null&&m.i==null&&m.j==null)
        query.append("a="+m.a);query.append(" d="+m.d);
    // ... 512 lines in this pattern
    return query.toString();

        return query.toString();
    }
}

我想以这样的方式编写public String build(Model m),以便我不必编写512 if-else条件。

条件:

  1. Model类的所有实例变量都可以有两个值(null,not null)

  2. 它们都可以为null或者它们都不能为空。

  3. 总共有512种组合(因为每个实例变量都有两个状态,并且有9个实例变量,所以条件总数将是2 ^ 9)

  4. 实例变量的顺序无关紧要。

  5. 我的项目使用Java 6,所以我不能在字符串上使用开关。

  6. 我已经研究过各种模式,但没有一种符合我的要求。

    感谢您寻找

6 个答案:

答案 0 :(得分:3)

如下的私人帮助方法应该这样做 -

private void appendIfNotNull(String fieldOp, String val) {
    if(val != null) {
        query.append(fieldOp).append(val);
    }
}

然后只需在build方法 -

中调用它
public String build(Model m) {
    appendIfNotNull("a=", m.a); //no null check, just need to repeat this for all fields

答案 1 :(得分:1)

也许您想尝试使用 Java Reflection 来阅读模型的所有字段并阅读它们。您不需要知道字段名称就可以阅读它。因此,即使您扩展了Model类,它也将是完全动态的和通用的。

    Class modelClass = Class.forName(Model.class.getName());
    Field[] fields = circleClass.getFields(); //includes all fields declared in you model class
    for (Field f : fields) {
        System.out.println("field " + f.getName() + " has value: " + f.get(<YOUR_MODEL_INSTANCE>));
    }

示例代码改编自:   - http://forgetfulprogrammer.wordpress.com/2011/06/13/java-reflection-class-getfields-and-class-getdeclaredfields/

答案 2 :(得分:1)

这段代码有意义吗?

interface ToStringer {
    void appendTo(StringBuilder sb);
}

class NullToStringer implements ToStringer {
    public void appendTo(StringBuilder sb) {
        // Do nothing
    }
}

class IntegerToStringer implements ToStringer {
    private String fieldName;
    private Integer val;
    public IntegerToStringer(String fieldName, Integer val) {
        this.fieldName = fieldName;
        this.val = val;
    }


    public void appendTo(StringBuilder sb) {
        sb.append(field).append(" = ").append(val);
    }
}

public class ToStringFactory {
    public ToStringer getToStringer(String fieldName, Integer val) {
        if (val == null) {
            return new NullToStringer();
        } else {
            return new IntegerToStringer(fieldName, val);
        }
    }       

    public ToStringer getToStringer(String fieldName, String val) {
        ...
    }
}

public String build(Model m){
    ArrayList<ToStringInstance> list = ...;
    list.add(ToStringFactory.getToStringer("f", m.f));
    list.add(ToStringFactory.getToStringer("g", m.g));
    list.add(ToStringFactory.getToStringer("h", m.h));

    StringBuilder sb = ...;

    for (ToStringInstance tsi : list) {
       tsi.appendTo(sb);
    }

    return sb.toString();

}

我不确定你想要实现什么逻辑,但是一般方法:创建接口,打印值的具体实现,使用NullValue模式隐藏null问题并使用工厂控制对象创建应该可以解决问题。

通过使用这种方法,您可以通过避免多个if-else语句来避免2 ^ 9组合的问题。

更新。刚想到我。你可以使用反射。遍历所有字段,获取每个字段的值,如果它不为空则打印它。也许这就足够了。

答案 3 :(得分:1)

正如我在评论中提到的,每个组合都不需要不同的if。您只需要附加非空值,并忽略那些值。如果这对您有用,请告诉我。

public String build(Model m) {
    // use this to know when to add " AND " to separate existing values
    boolean appended = false;

    if (m.a != null) {
        query.append("a=" + m.a);
        appended = true;
    }
    if (m.b != null) {
        if (appended) {
            query.append(" AND ");
        }
        query.append("b=" + m.b);
        appended = true;
    }
    if (m.c != null) {
        if (appended) {
            query.append(" AND ");
        }
        query.append("c=" + m.c);
        appended = true;
    }
    if (m.d != null) {
        if (appended) {
            query.append(" AND ");
        }
        query.append("d=" + m.d);
        appended = true;
    }
    if (m.e != null) {
        if (appended) {
            query.append(" AND ");
        }
        query.append("e=" + m.e);
        appended = true;
    }
    if (m.f != null) {
        if (appended) {
            query.append(" AND ");
        }
        query.append("f=" + m.f);
        appended = true;
    }
    if (m.g != null) {
        if (appended) {
            query.append(" AND ");
        }
        query.append("g=" + m.g);
        appended = true;
    }
    if (m.h != null) {
        if (appended) {
            query.append(" AND ");
        }
        query.append("h=" + m.h);
        appended = true;
    }
    if (m.i != null) {
        if (appended) {
            query.append(" AND ");
        }
        query.append("i=" + m.i);
        appended = true;
    }
    if (m.j != null) {
        if (appended) {
            query.append(" AND ");
        }
        query.append("j=" + m.j);
        appended = true;
    }
    return query.toString();
}

答案 4 :(得分:1)

您似乎希望为每个不是null的元素追加查询。这可以通过一两种辅助方法非常简单地完成:

public class Service {
    public StringBuilder query = null;  
    public Service(){
        query = new StringBuilder("Select * from A where ");
    }
    public String build(Model m) {
        boolean added = first;
        first &= !maybeAdd("a", m.a, first);
        first &= !maybeAdd("b", m.b, first);
        . . . // all the rest of the fields of m
    }

    /**
     * Add an equality test to an SQL query if the value is not {@code null}.
     * @param key the field name for the query
     * @param value the value to test for equality
     * @param first flag indicating that no conditions have been added
     * @return {@code true} if the value was appended; {@code false} otherwise.
     */    
    private boolean maybeAdd(String key, Object value, boolean first) {
        if (value != null) {
            if (!first) {
                query.append(" AND ");
            }
            query.append(key).append('=').append(value);
            return true;
        }
        return false;
    }
}

请注意,如果模型的所有字段均为null,则无法正确形成查询。您可能希望在maybeAdd方法中包含适当的逻辑来补偿它。

答案 5 :(得分:0)

我不知道为什么你需要两个if语句:

if( m.a == null) { 
  query.append("m=null");
} else { 
 query.append("m="+m.a);
}
if( m.b == null) { 
  query.append("m=null");
} else { 
 query.append("m="+m.b);
}