我在创建一个“部分”可变的对象时,发现使用构建器是否是正确的方法时遇到了麻烦,即某些对象的属性是可变的。
让我们考虑一下IGlass
接口的实现。一个最终的必需参数,一个可在创建对象后更改的可选参数:
public class SimpleGlass implements IGlass {
// Mandatory.
private final int size;
// Optional.
private boolean isEmpty;
private SimpleGlass(SimpleGlassBuilder builder) {
size = builder.getSize();
isEmpty = builder.isEmpty();
}
@Override
public int getSize() {
return size;
}
@Override
public boolean isEmpty() {
return isEmpty;
}
@Override
public void setEmpty(boolean isEmpty) {
this.isEmpty = isEmpty;
}
public static class SimpleGlassBuilder {
// Mandatory.
private final int size;
// Optional.
private boolean isEmpty = false;
public SimpleGlassBuilder(int size) {
this.size = size;
}
public SimpleGlassBuilder setEmpty(boolean isEmpty) {
this.isEmpty = isEmpty;
return this;
}
public IGlass build() {
return new SimpleGlass(this);
}
public int getSize() {
return size;
}
public boolean isEmpty() {
return isEmpty;
}
}
}
因此,构建器会创建可变对象,但是,只要编程文档中提到构建器,它就是不可变对象。
在这种情况下使用构建器是否可以?
答案 0 :(得分:7)
我想说,Builder用于具有大量属性的类,其中大部分属性都是可选的。您可以使用构建器并指定您需要的内容,而不是拥有一百万个构造函数或一个糟糕的构造函数。
new GlassBuilder(16_OZ).withHandle().withLogo(logo).build()
// instead of
new Glass(16_OZ,
/* handle? */ true,
/* chipped? */ false,
/* monogram? */ null,
/* something else? */ null,
logo);
最终的可变性很好,因为可变性很好,但它实际上并不影响Builder是否让你的生活更轻松。
答案 1 :(得分:1)
我会在IGlass实现类中保留“empty”属性,但是将其从构建器中删除。设置值的地方太多了。此外,如果您在构建器中将其设置为仅适用于在该点之后创建的IGlass实例并且仅在调用其“setEmpty()”方法之前,它会混淆该问题。
我建议你构建它们,然后在新构建的对象实例上设置'empty'属性。
设计模式的目的是使事情易于讨论和易于理解。通过添加额外的关注,即构建器或实例是否设置了“空”属性,事情就不再那么容易了。