简体   繁体   English

正确的折射if语句的方法

[英]Correct way to refractor if-statements

I wonder if this is a good way to refactor multiple if statements? 我想知道这是否是重构多个if语句的好方法? What I have heard is that if-statements are "bad" practice and i would like to take my programing to the next level by refactor some of my code. 我听到的是if语句是“不好的”做法,我想通过重构一些代码将程序提高到一个新的水平。

Original code: 原始代码:

public int Colors(String col, int row){
    int ret = 0;
    if(col.equals("R")){
        ret = Color.parseColor("#EF5350");
    }else if(col.equals("B")) {
        ret = Color.parseColor("#7986CB");
    }else if(col.equals("V")){
        ret = Color.WHITE;
    }else if(col.equals("G")){
     ret = Color.parseColor("#FFE082");
    }else if(Math.floorMod(row,2) == 0){
        ret = Color.parseColor("#e0e0e0");
    }else{
         ret = Color.parseColor("#eeeeee");
    }

return ret; 返回ret } }

New code: 新代码:

public int Colors(String col, int row){

    Map<String,Integer> ColorMap1 = new HashMap<>();

    ColorMap1.put("R", Color.parseColor("#EF5350"));
    ColorMap1.put("B",Color.parseColor("#7986CB"));
    ColorMap1.put("V",Color.parseColor("#FFE082"));
    ColorMap1.put("G",Color.parseColor("#FFFFFF"));

    Integer current = ColorMap1.get(col);

    Map<Integer,Integer> ColorMap2 = new HashMap<>();

    ColorMap2.put(0,Color.parseColor("#e0e0e0"));
    ColorMap2.put(1,Color.parseColor("#eeeeee"));

    Integer current2 = ColorMap2.get(Math.floorMod(row,2));

    return  current != null ? current  : current2 ;

} }

If-statements aren't inherently bad. If语句并不是天生就糟糕的。 They can be a bit clunky for large comparison blocks, but in Java, there's no universal alternative. 对于较大的比较块,它们可能有些笨拙,但是在Java中,没有通用的替代方法。 (You could use when in Kotlin.) (你可以使用when在科特林。)

Since you've got a big block there, and you're comparing Strings, you can always use a switch statement, for most of it: 由于那里有一个很大的块,并且您正在比较字符串,因此对于大多数情况,您始终可以使用switch语句:

public int colors(String col, int row) //method names in Java should usually use camelCase, not TitleCase
    switch(col) {
        case "R":
            return Color.parseColor("#EF5350");
        case "B":
            return Color.parseColor("#7986CB");
        case "V":
            return Color.WHITE;
        case "G":
            return Color.parseColor("#FFE082");
        default: //comparable to an "else" statement
            if (Math.floorMod(row, 2) == 0) return Color.parseColor("#e0e0e0");
            else return Color.parseColor("#eeeeee");
    }
}

if in general is not bad practice. if一般来说是不错的做法。 It's just that when you find yourself using multiple chained if - else if blocks in a row, that's usually code smell that indicates you could be doing what you are doing more efficiently. 只是当您发现自己使用多个链式ifelse if连续else if块时,这通常是代码味道,表明您可以更高效地完成工作。

In this case, using a static Map is a good way to refactor your most of your code to be more efficient than the if equivalent. 在这种情况下,使用静态Map是一种重构大多数代码的有效方法,其效率要高于if等效项。 The problem is that, because one of the conditions doesn't match the rest and it isn't a constant value. 问题在于,因为其中一个条件与其余条件不匹配,并且它不是恒定值。 So you can partially refactor your code like this: 因此,您可以像下面这样部分重构代码:

static HashMap<String, Color> colorMap;

static {
    colorMap = new HashMap<>();
    colorMap.put("R",Color.parseColor("#EF5350"));
    colorMap.put("B",Color.parseColor("#7986CB"));
    colorMap.put("V",Color.parseColor("#FFE082"));
    colorMap.put("G",Color.parseColor("#FFFFFF"));
}

// ...

public int Colors(String col, int row) {
    if (colorMap.containsKey(col)) {
      return colorMap.get(col);
    }

    if (Math.floorMod(row, 2) == 0) {
      return Color.parseColor("#e0e0e0");
    }

    return Color.parseColor("#eeeeee");
}

Alternatively, you can accomplish a similar thing with a switch block: 另外,您可以使用switch块完成类似的switch

public int Colors(String col, int row) {
    switch (col) {
        case "R": return Color.parseColor("#EF5350");
        case "B": return Color.parseColor("#7986CB");
        case "V": return Color.parseColor("#FFE082");
        case "G": return Color.parseColor("#FFFFFF");
    }

    if (Math.floorMod(row, 2) == 0) {
      return Color.parseColor("#e0e0e0");
    }

    return Color.parseColor("#eeeeee");
}

It's arguable that if-statements or switch-statements are always bad. 有争议的是, if-statementsswitch-statements总是不好的。 Sometimes they lead to much more concise code. 有时它们导致更简洁的代码。 But if number of cases grows really high, then it becomes cleaner to use Map . 但是,如果案例数量确实增加很多,那么使用Map会变得更加干净。

You can use map registry for colors as follows: 您可以将地图注册表用于颜色,如下所示:

public class SomeClass {
    private static int DEFAULT_COLOR = Color.parseColor("#eeeeee");
    private static Map<ColorKey, Integer> COLORS = new HashMap<>();
    static {
        COLORS.put(ColorKey.of("R", null), Color.parseColor("#EF5350"));
        COLORS.put(ColorKey.of("B", null), Color.parseColor("#7986CB"));
        COLORS.put(ColorKey.of("V", null), Color.WHITE);
        COLORS.put(ColorKey.of("G", null), Color.parseColor("#FFE082"));
        COLORS.put(ColorKey.of(null, 0), Color.parseColor("#e0e0e0"));
    }

    public Integer colors(String col, int row) {
        return COLORS.getOrDefault(ColorKey.of(col, row), DEFAULT_COLOR);
    }

    private static final class ColorKey {
       private final String col;
       private final Integer row;
       private ColorKey(String col, Integer row) {
           this.col = col; this.row = row;
       }
       private static ColorKey of(String col, Integer row) {
           return new ColorKey(key(col), key(row));
       }
       private static String key(String col) {
           Set<String> columns = new HashSet<>(Arrays.asList("R", "B", "V", "G"));
           return columns.contains(col) ? col : null;
       }
       private static Integer key(Integer row) {
           return row != null && Math.floorMod(row,2) == 0 ? Integer.valueOf(0) : null;
       }
       @Override
       public boolean equals(Object obj) {
           if (obj == null) return false;
           if (obj == this)  return true;
           if (!(obj instanceof ColorKey)) return false;
           ColorKey that = (ColorKey) obj;
           return Objects.equals(this.col, that.col) && Objects.equals(this.row, that.row);
       }
       @Override
       public int hashCode() {
           int result = 17;
           result = 31 * result + Objects.hash(col);
           result = 31 * result + Objects.hash(row);
           return result;
       }
    }
}

If statement is bad practice if you used it excessively and in different places. If在不同的地方使用了过多的if语句,则是不好的做法。 The best way to refactor it is to use a design pattern There are many patterns can be used instead of if statement, like strategy , state or command pattern 重构的最佳方法是使用设计模式可以使用许多模式来代替if语句,例如strategystatecommand模式

You can use enum to add different colors: 您可以使用enum添加不同的颜色:

public class Main
{
    public static void main(String[] args) {
        String colorName = "R";
        int row = 23;
        System.out.println("Color code: " + ColorSchema.getColor(colorName, row).getCode());
    }
}


enum ColorSchema {

  R("#EF5350"), 
  B("#7986CB"), 
  V("#FFE082"),
  G("#FFFFFF"),

  ROW0("#e0e0e0"),
  ROW1("#eeeeee");

  private String color;

  ColorSchema(String color) {this.color = color;}
  public int getCode(){ return Color.parseColor(color);}

  public static ColorSchema getColor(String name, int row) {
    for (ColorSchema c : ColorSchema.values()) {
      if (c.color.equals(name)) {
        return c;
      }
    }
    return ColorSchema.valueOf("ROW" + Math.floorMod(row, 2));
  }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM