Java 如果使用范围数据,则解决方案优于其他解决方案

Java 如果使用范围数据,则解决方案优于其他解决方案,java,Java,我有一个简单的java方法,它根据从RGB转换的HSB值返回颜色。它可以工作(需要一些调整),但我使用了一系列else-if和嵌套if语句来返回所需的数据。我听说hashmap和字符串工厂更好,但我看不出它们是如何处理范围数据的。有没有更好的解决方案可以处理这样的范围数据 片段: public static String getColorName() { getHSB(rgb); if(hsbH >= 45 && hsbH < 75) {

我有一个简单的java方法,它根据从RGB转换的HSB值返回颜色。它可以工作(需要一些调整),但我使用了一系列else-if和嵌套if语句来返回所需的数据。我听说hashmap和字符串工厂更好,但我看不出它们是如何处理范围数据的。有没有更好的解决方案可以处理这样的范围数据

片段:

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";
        }
...
公共静态字符串getColorName(){
getHSB(rgb);
如果(hsbH>=45&&hsbH<75){
如果(hsbS>0&&hsbS<45&&hsbB>70){
返回“白色/灰白色”;
}否则如果(hsbS>0&&hsbS<45&&hsbB<10){
返回“深黄色”;
}否则{
返回“黄色”;
}
}否则如果(hsbH>=15&&hsbH<45){
如果(hsbS>0&&hsbS<45&&hsbB>70){
返回“白色/灰白色”;
}否则如果(hsbS>0&&hsbS<45&&hsbB<10){
返回“深橙色”;
}否则{
返回“橙色”;
}
...

如果只有一个范围维度,可以使用带或的。但是对于多个范围维度,我不知道如何实现这一点

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

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 ;
    }

}
并将它们与字符串一起保存在映射中(您可能需要首先实现equals()/hashCode()


现在,在映射的entrySet()上迭代,当规则应用时,您就有了自己的颜色名称。

仔细看,您的代码中有大量重复和非常明显的结构!以下是我的想法,据我记忆所及,大部分工作都是在我最喜欢的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;
}
请注意,
colorRanges
范围应定义一次并重新使用


冒着被否决的风险,你可以用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) {
        //...
    }
}

创建HSB类肯定会使代码更具可读性。下面我使用的是
TreeMap
ceilingEntry()
方法,可以说它的可读性不如大量具有显式最小值和最大值的if语句。然而,它还有一个额外的好处,就是不会留下任何漏洞。(即,如果有人设置了0-5、6-10等范围,
if
语句需要包含一个
作为比较的一部分,否则会有一个间隙。)

公共类HueSatBright{
int色调、sat、亮度;
静态TreeMap colorMap=newtreemap();
静止的{
颜色映射。放置(15,“红色”);
彩色地图。放置(45,“橙色”);
颜色映射。放置(75,“黄色”);
}
HueSatBright(整数色调、整数sat、整数亮度){
this.hue=色调;
this.sat=sat;
这个。亮度=亮度;
}
公共字符串toString(){
return(isKindaWhite())?“白色/灰白色”:getModifier()+getBaseColor();
}
公共布尔值isKindaWhite(){
返回(sat>0和sat<45和亮度>70);
}
公共字符串getModifier(){
返回(sat<10)-“暗”:“;
}
公共字符串getBaseColor(){
返回colorMap.ceilingEntry(hue.getValue();
}
}

为什么不将
name
添加到
ColorRule
中,而不是在地图中进行黑客攻击?然后,在应用程序开始时,在一些已知的颜色列表中创建并定义颜色规则,要查找颜色,只需在列表中进行findAll。
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());
}
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(toIntBetween(hsbH).between(45).and(75))
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();
    }

}