2011-08-31 18 views
7

Tengo un método simple de Java que devuelve los colores en función del valor de HSB convertido a partir de un RGB. Funciona (necesita algunos ajustes), pero utilizo una serie de sentencias else if y anidado para devolver los datos que deseo. Había oído que HashMaps y String Factories eran mejores, pero no podía ver cómo funcionaban con los datos a distancia. ¿Hay alguna solución mejor que funcione con datos a distancia como este?Mejor solución que otra, si con datos a distancia

Fragmento:

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

Respuesta

1

Mire con atención, hay una gran cantidad de repeticiones y una estructura muy obvia en su código. Esto es lo que ocurrió con, por lo que yo recuerdo la mayor parte del trabajo ya estaba hecho usando refactorizaciones automáticas en mi IDE favorito:

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

Si utiliza el asesoramiento de utilizar TreeMap este código Sean Patrick Floyd 's será aún más sencillo (I pude evitarlo):

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

Tenga en cuenta que colorRanges rangos deben definirse una vez y volver a utilizar.


arriesgarse a ser downvoted aquí es una buena manera de poder escribir esto utilizando literalmente Scala y DSL simple:

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) { 
     //... 
    } 
} 

Fantasía if(hsbH between 45 and 75) constructo se traduce en realidad a:

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

Si usted tiene una sola dimensión rango, se puede utilizar un TreeMap con floorEntry() o ceilingEntry(). Pero para las dimensiones de rango múltiple, realmente no veo cómo hacer que esto suceda.

En su lugar, lo que haría es especificar algún tipo de objeto regla:

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

} 

construirlos como esto:

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

y mantenerlos en un mapa junto con las cuerdas (que' Probablemente quiera implementar equals()/hashCode() primero).

Ahora itere sobre entrySet() del mapa, y cuando se aplica una regla, tiene su nombre de color.

+0

lugar de piratear un mapa, ¿por qué no agregar 'nombre' al' ColorRule'? Luego, al inicio de la aplicación, las reglas de color se crean y definen en una lista de colores conocida, y para buscar un color, solo hace un FindAll en la lista. –

+0

@Stefan Tienes razón, eso sería mejor. –

1

Creación de una HSB la clase definitivamente podría hacer que el código sea más legible. A continuación estoy usando el método ceilingEntry() de TreeMap que podría argumentarse es menos legible que una multitud de declaraciones if con mínimos y máximos explícitos. Sin embargo, tiene el beneficio adicional de no dejar ningún agujero. (Es decir, si alguien establece intervalos de 0-5, 6-10, etc., los if declaraciones necesitan incluir un <= o => como parte de la comparación o habrá un hueco.)

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

} 
Cuestiones relacionadas