目前我有这个代码(我不喜欢它):
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;
}
...
}
我该如何改进?
我有一些关于引入一个对象的想法,该对象将包含所有这些参数作为字段,然后,也许,可以应用构建器模式。但仍然没有明确的愿景如何实现,我不确定它是否值得做。还有其他想法吗?
答案 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;
}