我有一个 DownloadFile 类,具有以下属性
构造
DownloadFile (String name, String url, String from, String by, Boolean isDownloaded)
必填参数:
可选参数:
我从 20 不同位置调用我的DownloadFile类(当用户单击列表上的按钮,任何已启动的活动,服务,推送通知,特定警报时,任何广播接收等)。
new DownloadFile(name, url, from, by, false);
问题:
每当我想添加新参数时,我需要更改类+20个不同的呼叫位置
例如,我想添加第三个必填参数( 尺寸 )
新强制参数:
存在构建器模式的良好解释here
Joshua Bloch在Effective Java,第2版中说:
在设计构造函数或静态工厂具有多个参数的类时,构建器模式是一个不错的选择。
问题:
问题依然存在,如果强制参数中有加法,我需要更改班级+20个不同的呼叫位置
Google建议避免dependency injection frameworks like Roboguice,而Dagger 2是Google建议的唯一DI。
我之前没有使用和查看Dagger2,我发现basic tutorial手上的this answer by one of its founder和https://brajeshwar.github.io/entities/
答案 0 :(得分:1)
首先,您的示例不使用' telescoping构造函数'图案。伸缩构造函数的一个例子与你给定的代码有点一致,如下所示:
public DownloadFile(@NonNull String name, @NonNull String url) {
this.name = name;
this.url = url;
}
public DownloadFile(@NonNull String name, @NonNull String url, @NonNull String from) {
this(name, url);
this.from = from;
}
public DownloadFile (@NonNull String name, @NonNull String url, @Nullable String from, @Nullable String by, @Nullable Boolean isDownloaded) {
this(name, url);
this.from = from;
this.by = by;
this.isDownloaded = isDownloaded;
}
根据您的规范,您会遇到许多参数类型为String
的问题,并且您无法指定这两者之间的差异:
//duplicate constructor signatures - won't compile
public DownloadFile(@NonNull String name, @NonNull String url, @NonNull String from) {
this(name, url);
this.from = from;
}
public DownloadFile(@NonNull String name, @NonNull String url, @NonNull String by) {
this(name, url);
this.by = by;
}
像Dagger这样的依赖注入框架不太可能有所帮助;依赖注入框架用于依赖项,您传递给DownloadFile
的是参数。
正如Effective Java中所建议的,构建器是一个很好的选择。如果您认为添加额外的强制参数会改变20个地方的签名,我不确定您是否完全理解了构建器模式。在使用构建器的位置,您只需手动添加必需参数setMandatoryParameter(String extraMandatoryParameter);
。如果您需要额外的强制参数,您将始终必须执行某事。
//old
new DownloadFile.Builder()
.setName(String name)
.setFrom(String from)
.build();
//a wild mandatory parameter appears
new DownloadFile.Builder()
.setName(String name)
.setFrom(String from)
.setExtraMandatoryParameter(String extraMandatoryParameter)
.build();
也许你在考虑默认值 - 让我们说你有一个额外的强制性参数String
但是你不想担心一直设置它,因为在大多数情况下它将是一个默认字符串"默认"。然后,您只需在构造函数中指定DownloadFile.Builder
:
public Builder() {
this.extraMandatoryParameter = "default"
}
如有必要,您仍然可以覆盖默认值:
public Builder setExtraMandatoryParameter(String extraMandatoryParameter) {
this.extraMandatoryParameter = extraMandatoryParameter;
return this;
}
如果您使用的是Android Studio,则IDE甚至可以通过Replace constructor with builder选项为您执行此操作。
答案 1 :(得分:0)
在Effective Java 3rd Edition中,它还添加了JavaBeans模式。
具有必需参数的构造函数
public DownloadFile(String name, String url)
{
this.name = name;
this.url = url;
}
然后为每个可选字段添加setter:
public void setFrom(String from) { this.from = from; }
public void setBy(String by) { this.by = by; }
public void setIsDownloaded(Boolean isDownloaded) { this.isDownloaded = isDownloaded; }
但是@DavidRawson构建器的例子在我看来是最好的解决方案。 如Effective Java中所述
在这种模式中,您可以在许多调用中构造对象,
通常你想在构造函数调用之后拥有'真正的'对象。