2010-04-30 91 views
4

目前,我有这样的代码(我不喜欢它):如何将默认值设置为方法的所有错误或空参数?

private RenderedImage getChartImage (GanttChartModel model, String title, 
            Integer width, Integer height, 
            String xAxisLabel, String yAxisLabel, 
            Boolean showLegend) { 
    if (title == null) { 
     title = ""; 
    } 
    if (xAxisLabel == null) { 
     xAxisLabel = ""; 
    } 
    if (yAxisLabel == null) { 
     yAxisLabel = ""; 
    } 
    if (showLegend == null) { 
     showLegend = true; 
    } 
    if (width == null) { 
     width = DEFAULT_WIDTH; 
    } 
    if (height == null) { 
     height = DEFAULT_HEIGHT; 
    } 
    ... 
} 

我怎么能提高呢?

我有一些关于引入一个将包含所有这些参数作为字段的对象的想法,然后,也许可以应用生成器模式。但是仍然没有清晰的眼光来实现这一点,我不确定这是值得做的。任何其他想法?

回答

3

所以很多参数一种方法绝对是一种代码味道。我会说Chart对象正在等待诞生。这是一个基本的轮廓:

private RenderImage getChartImage(Chart chart) { 
    //etc. 
} 
private static class Chart { 
     private GanttChartModel model; 
     private String title = ""; 
     //etc, initializing each field with its default value. 
     private static class Builder { 
      private Chart chart; 
      public Builder(GanttChartModel model) { 
       chart = new Chart(); 
       chart.model = model; 
      } 
      public setTitle(String title) { 
       if (title != null) { 
        chart.title = title; 
       } 
      } 
     } 
    } 

其他选项包括使用的方法,而不是对象,表明空原语是不允许的,虽然这并不一定做的更好。另一个选择是一堆重载方法,但是在给定参数类型的情况下,这并不实际,因为我认为你想让任何参数成为可选参数,而不是第一个参数是必需的,而后面的参数是可选的。

1

您的方法的目的是构造一个复杂的对象。因此,生成器模式似乎适用于解决此问题。构建器可以管理许多用于创建对象的选项。

图像的某些属性不应该有默认值。例如,没有标题的图像不是很有用,但这取决于您的应用程序的需求。

使用的助洗剂可以是这样的:

RenderedImage image = RenderedImageBuilder.getNew(model) 
         .title("title").width(100).height(100) 
         .showLegend().build(); 

建设者的另一个优点是,他们可以很容易地记录了参数的任何违约,它们应该如何使用。

0

那么,我在想有没有一些框架支持@NotNull注释,如果一个方法有这个注释,框架将检查所有的参数。

@NotNull public void doSomething(Parameter a, Parameter b) { }

1

我能想到的手,最好是引进Parameter Object(这也将是一个建设者)呼吁像ChartOptions包含此方法的所有选项。

对象可堆垒起来:

ChartOptions options = new ChartOptions() 
    .setHeight(10) 
    .setWidth(100) 

getChartImage(model, options); 

如果不工作,你至少可以封装空校验:

private <A> A checkNull(A object, A default) 
{ 
    return object == null ? default : object; 
} 
1

我会将该逻辑移动到您要返回对象的类的setter方法中。

public class MyRenderedImage implements RenderedImage { 

    public MyRenderedImage(String title, ...) { 
     // constructor should call setters that do validation/coercion 
    } 

    public void setTitle(String title) { 
     if (title == null) { 
      this.title = ""; 
     } 
    } 

    ... 
} 

另一种选择要考虑的是抛出一个InvalidArgumentException,但它听起来像是你已经知道你想要做什么。

0

您可以拥有最初构建的地图值。你可以这样做,

private RenderedImage getChartImage(GanttChartModel model, String title, 
     Integer width, Integer height, String xAxisLabel, 
     String yAxisLabel, Boolean showLegend) { 

    title = removeNull(KEY_TITLE,title); 
    xAxisLabel = removeNull(KEY_X,xAxisLabel); 
    yAxisLabel = removeNull(KEY_Y,yAxisLabel); 
    showLegend = removeNull(KEY_LEG,showLegend); 
    width = removeNull(KEY_W,width); 
    height = removeNull(KEY_H,height); 
} 

//initialize the defaultMap with the key-value of default pairs 
Map<Object,Object> defaultMap; 

private Object removeNull(Object keyTitle, Object value) { 
    if(value==null){ 
     return defaultMap.get(keyTitle); 
    } 
    return value; 
} 
相关问题