如何将默认值设置为方法的所有错误或空参数?

时间:2010-04-30 13:30:24

标签: java oop refactoring

目前我有这个代码(我不喜欢它):

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

我该如何改进?

我有一些关于引入一个对象的想法,该对象将包含所有这些参数作为字段,然后,也许,可以应用构建器模式。但仍然没有明确的愿景如何实现,我不确定它是否值得做。还有其他想法吗?

6 个答案:

答案 0 :(得分: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;
                }
           }
      }
  }

其他选项包括在方法上使用基元而不是对象来指示不允许使用null,尽管这并不一定会使它更好。另一个选项是一堆重载方法,但是在这里给出了参数的类型,这并不真正起作用,因为我认为你想让任何参数都是可选的,而不是让第一个参数需要,后续的可选。

答案 1 :(得分:1)

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

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

使用构建器可能如下所示:

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

构建器的另一个优点是,它们可以很容易地记录参数的任何默认值以及如何使用它们。

答案 2 :(得分:1)

我能想到的最好的方法是引入一个名为ChartOptions的{​​{3}}(也将是一个构建器)来包含此方法的所有选项。

该对象可以零碎地构建:

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

getChartImage(model, options);

等。

如果这不起作用,您至少可以封装空检查:

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

答案 3 :(得分: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,但听起来你已经知道自己想做什么了。

答案 4 :(得分:0)

好吧,我在考虑是否有一些框架支持@NotNull注释,如果方法有这个注释,框架将检查它的所有参数。

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

答案 5 :(得分: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;
}