使用构建器构建“部分”可变对象?

8
我遇到了一些困难,无法确定在创建一个“部分”可变的对象时是否使用构造器是正确的方法,即该对象的某些属性是可变的。
让我们考虑一个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;
        }
    }
}

因此,建造者创建的是可变对象,但是在编程文献中提到建造者时,通常是指不可变对象。

在这种情况下使用建造者是否可行?


4
建造者模式主要用于创建一个类的实例,这个类可能需要许多设置参数。这并不意味着您不能为可变对象创建建造者。 - frictionlesspulley
2个回答

12

我认为Builder主要用于拥有许多属性且大部分属性是可选的类。使用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

我会在IGlass实现类中保留"empty"属性,但从构建器中删除它。有太多地方可以设置该值。而且如果在构建器中设置它,这会使问题变得混乱,因为它仅适用于在此之后创建的IGlass实例,并且仅在调用其'setEmpty()'方法之前。

我建议您先构建它们,然后在新构建的对象实例上设置'empty'属性。

设计模式的目的是使事情易于讨论和理解。通过增加构建器或实例设置'empty'属性的额外关注点,事情就不再那么简单了。


好的观点,但如果我在对象创建时有许多可选变量参数,作为客户端该怎么办?例如,我创建一个具有两个必需参数、三个可选最终参数和十个可选变量参数的对象。我会为Builder...build()部分编写一行代码,然后在另外十行上设置其他参数吗? :-/ - htorque

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接