2011-08-31 56 views
7

我有一个简单的java方法,它根据从RGB转换而来的HSB值返回颜色。它工作(需要一些调整),但我使用一系列的其他if和if嵌套语句来返回我想要的数据。我听说HashMaps和字符串工厂比较好,但是我看不到这些工具如何处理远程数据。是否有更好的解决方案可以处理像这样的范围数据?如果使用范围数据,比其他解决方案更好的解决方案

段:

public static String getColorName() { 
    getHSB(rgb); 
    if(hsbH >= 45 && hsbH < 75) { 
     if(hsbS > 0 && hsbS < 45 && hsbB > 70){ 
      return "White/Off White"; 
     } else if(hsbS > 0 && hsbS < 45 && hsbB < 10) { 
      return "Dark Yellow"; 
     } else { 
      return "Yellow"; 
     } 
    } else if(hsbH >= 15 && hsbH < 45) { 
     if(hsbS > 0 && hsbS < 45 && hsbB > 70){ 
      return "White/Off White"; 
     } else if(hsbS > 0 && hsbS < 45 && hsbB < 10) { 
      return "Dark Orange"; 
     } else { 
      return "Orange"; 
     } 
... 

回答

1

仔细看,代码中有很多重复和非常明显的结构!以下是我想出了,据我记忆最深的作业中我最喜欢的IDE使用自动重构做:

public static String getColorName() { 
    getHSB(rgb); 
    if (hsbH < 15) 
     return colorName(hsbB, hsbS, "Red"); 
    if (hsbH < 45) 
     return colorName(hsbB, hsbS, "Orange"); 
    if (hsbH < 75) 
     return colorName(hsbB, hsbS, "Yellow"); 
    //... 
} 

private static String colorName(int hsbB, int hsbS, String color) { 
    final boolean smallSaturation = hsbS > 0 && hsbS < 45; 
    if (smallSaturation) { 
     if (hsbB > 70) 
      return "White/Off White"; 
     if (hsbB < 10) 
      return "Dark " + color; 
    } 
    return color; 
} 

如果使用使用TreeMap这个代码的肖恩·帕特里克·弗洛伊德的建议会更简单(我可以帮助自己):

public static String getColorName(final int hsbH, final int hsbB, final int hsbS) { 
    NavigableMap<Integer, String> colorRanges = new TreeMap<Integer, String>(); 
    colorRanges.put(0, "Red"); 
    colorRanges.put(15, "Orange"); 
    colorRanges.put(75, "Yellow"); 
    //... 
    return colorName(hsbB, hsbS, colorRanges.floorEntry(hsbH).getValue()); 
} 

注意colorRanges范围应被定义一次和重用。


冒着被这里downvoted是你可以写这个字面上使用Scala和简单的DSL的好方法:

implicit def toIntBetween(x: Int) = new { 
    def between(left: Int) = new { 
     def and(right: Int) = { 
      x >= left && x < right 
     } 
    } 
} 

def getColorName = { 
    if(hsbH between 45 and 75) { 
     //... 
    } 
} 

花式if(hsbH between 45 and 75)结构实际上翻译为:

if(toIntBetween(hsbH).between(45).and(75)) 
5

如果你有一个范围的尺寸,你可以使用一个TreeMapfloorEntry()ceilingEntry()。但是对于多个范围维度,我并不真正看到如何实现这一点。

相反,我会做的就是指定某种规则的对象:

public class Rule{ 

    private int maxH = Integer.MAX_VALUE; 
    private int maxS = Integer.MAX_VALUE; 
    private int maxB = Integer.MAX_VALUE; 
    private int minH = Integer.MIN_VALUE; 
    private int minS = Integer.MIN_VALUE; 
    private int minB = Integer.MIN_VALUE; 

    public Rule maxH(int maxH){this.maxH=maxH;return this;} 
    public Rule minH(int minH){this.minH=minH;return this;} 
    public Rule maxS(int maxS){this.maxS=maxS;return this;} 
    public Rule minS(int minS){this.minS=minS;return this;} 
    public Rule maxB(int maxB){this.maxB=maxB;return this;} 
    public Rule minB(int minB){this.minB=minB;return this;} 

    public boolean appliesTo(HSB hsb){ 
     return minH < hsb.getH() && hsb.getH() < maxH && 
       minB < hsb.getB() && hsb.getB() < maxB && 
       minS < hsb.getS() && hsb.getS() < maxS ; 
    } 

} 

构建它们是这样的:

Rule rule = new Rule().maxB(123).minH(45).maxH(122); 

并与字符串一起保存在一个地图(你”你可能想要首先实现equals()/ hashCode()。

现在迭代地图的entrySet(),当规则适用时,你有你的颜色名称。

+0

相反为什么不在'ColorRule'中添加'name'?然后,在应用程序的开始处,颜色规则将在一些已知的颜色列表中创建和定义,并且您只需在列表中查找一个颜色即可查找所有颜色。 –

+0

@Stefan你说得对,那会更好。 –

1

创建HSB类可以使代码更具可读性。下面我使用的ceilingEntry()方法TreeMap可能会被认为比许多含有明确的最小值和最大值的if语句更不可读。但是,它具有不留任何缺陷的附加好处。 (即,如果某人建立的0-5范围,6-10,等等,if语句需要包括一个或<==>作为比较的一部分或者将有间隙。)

public class HueSatBright { 
    int hue,sat, brightness; 

    static TreeMap<Integer,String> colorMap = new TreeMap<Integer,String>(); 

    static { 
     colorMap.put(15,"Red"); 
     colorMap.put(45,"Orange"); 
     colorMap.put(75,"Yellow"); 
    } 

    HueSatBright(int hue, int sat, int brightness) { 
     this.hue = hue; 
     this.sat = sat; 
     this.brightness = brightness; 
    } 

    public String toString() { 
     return (isKindaWhite()) ? "White/Off White" : getModifier() + getBaseColor(); 
    } 

    public boolean isKindaWhite() { 
     return (sat > 0 && sat < 45 && brightness > 70); 
    } 

    public String getModifier() { 
     return (sat < 10) ? "Dark " : ""; 
    } 

    public String getBaseColor() { 
     return colorMap.ceilingEntry(hue).getValue(); 
    } 

}