如何在if语句中简化这样的重复代码?

时间:2018-05-04 06:35:41

标签: java if-statement optimization duplicates

我认为这是网络项目中非常常见的情况。假设有一个实体,例如:

//JAVA code
@Data
class Entity{

    private String a;
    private String aExt;

    private String b;
    private String bExt;

    private String c;
    private String cExt;

    ... something more ...
}

出于某种目的,我需要根据传递的参数从Entity获取部分值,例如:

public ViewObject foo(Entity entity, String condition){

    ViewObject vo = new ViewObject();

    if("aRelated".equals(condition)){
        vo.setValue1(entity.getA());
        vo.setValue2(entity.getAExt());
    }
    else if("bRelated".equals(condition)){
        vo.setValue1(entity.getB());
        vo.setValue2(entity.getBExt());
    }
    else if(cRelated".equals(condition)){
        vo.setValue1(entity.getC());
        vo.setValue2(entity.getCExt());
    }
    ... else statement if there are other values ....

    return vo;
}

我知道我可以使用switch-case语句来减少foo()中的某些字词,但与if-else相比没有本质区别,特别是当Entity有很多变量时

作为一个简单的例子,foo()只是一个视图对象构建器,但我的项目更复杂,每个{{strong>只有不同的变量名称有许多重复的代码{1}}陈述。

如何减少上述重复代码?

4 个答案:

答案 0 :(得分:3)

您可以尝试创建两个哈希映射:

// name these properly!
HashMap<String, Function<Entity, String>> valueMap = new HashMap<>();
HashMap<String, Function<Entity, String>> extMap = new HashMap<>();

添加这些KVP:

// valueMap
"aRelated" - Entity::getA
"bRelated" - Entity::getB
"cRelated" - Entity::getC

// extMap
"aRelated" - Entity::getAExt
"bRelated" - Entity::getBExt
"cRelated" - Entity::getCExt

现在,您可以在没有if语句的情况下执行此操作:

vo.setValue1(valueMap.get(condition).apply(entity));
vo.setValue2(extMap.get(condition).apply(entity));

答案 1 :(得分:1)

另一种选择是使用反射:

import java.lang.reflect.Method;
import java.lang.reflext.InvocationTargetException;

...

public ViewObject foo(Entity e, String c) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
  String[] methodNames = { "get" + c.substring(0,1).toUpperCase(), "get" + c.substring(0,1).toUpperCase() + "Ext" }; 
  Method[] methods = { e.getClass().getDeclaredMethod(methodNames[0]), e.getClass().getDeclaredMethod(methodNames[1]) };
  ViewObject vo = new ViewObject();                                                                                                   

  vo.setValue1((String)methods[0].invoke(e));                                                                                         
  vo.setValue2((String)methods[1].invoke(e));                                                                                         

  return vo;                                                                                                                          
}

虽然我不得不承认我个人更喜欢其他答案的地图方法,只是显示更多选项。

答案 2 :(得分:0)

使用地图可以解决问题:

class EntityPart {
    String s;
    String sExt;
}

class Entity {
    Map<String,EntityPart> m = new HashMap<>();
    m.add("aRelated",new EntityPart());
    m.add("bRelated",new EntityPart());
    ....
}

public ViewObject foo(Entity entity, String condition) {
    ViewObject vo = new ViewObject();
    EntityPart ep = entity.m.get(condition);
    vo.setValue1(ep.s);
    vo.setValue2(ep.sExt);
    return vo;
}

答案 3 :(得分:0)

将实体设为enum而不是类。

public enum Entity {

    A("a", "aExt"), B("b", "bExt"), C("c", "cExt");

    private final String name;
    private final String text;

    private Entity(String name, String text) {
        this.name = name;
        this.text = text;
    }

    public String getName() {
        return name;
    }

    public String getText() {
        return text;
    }

    public static Entity fromString(String raw) {

        return LOOKUP.get(raw);
    }

    private static final Map<String, Entity> LOOKUP = new HashMap<>();

    static {

        for (Entity e : values()) {
            LOOKUP.put(e.getName(), e);
        }
    }
}

并将您的foo方法修改为

public ViewObject foo(String condition){

    /*
     *  pass condition as "a", "b", "c" only not "aRelated", "bRelated", "cRelated"
     * 
     */
    ViewObject vo = new ViewObject();
    Entity e = Entity.fromString(condition); 
    if(null != e) {
        vo.setValue1(e.getName());
        vo.setValue2(e.getText());
    }
    return vo;
}