2011-08-31 87 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(); 
    } 

}