【问题标题】:Using a builder to build "partially" mutable objects?使用构建器构建“部分”可变对象?
【发布时间】:2012-12-27 20:49:24
【问题描述】:

在创建“部分”可变的对象时,我很难确定使用构建器是否是正确的方法,即对象的某些属性是可变的。

让我们考虑这个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;
        }
    }
}

因此,构建器创建了可变对象,但是,每当在编程文献中提到构建器时,它都是关于不可变对象的。

在这种情况下可以使用构建器吗?

【问题讨论】:

  • 构建器模式主要有助于创建可能需要许多设置参数的类的实例,这并不一定意味着您不能拥有可变对象的构建器

标签: java design-patterns builder


【解决方案1】:

我会说 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 是否让你的生活更轻松。

【讨论】:

    【解决方案2】:

    我会在 IGlass 实现类中保留“空”属性,但将其从构建器中删除。设置值的地方太多。另外,如果您在构建器中设置它会混淆问题,因为这仅适用于在该点之后创建的 IGlass 实例,并且仅在调用它们的 'setEmpty()' 方法之前。

    我建议你构建它们,然后在新建的对象实例上设置“空”属性。

    设计模式的目的是让事情变得容易谈论和理解。通过添加构建器或实例是否设置“空”属性的额外关注,事情不再那么容易了。

    【讨论】:

    • 好点,但如果我有许多可选的变量参数,我(作为客户)在创建对象时会做什么?例如,我创建了一个包含两个强制参数、三个可选最终参数和十个可选变量参数的对象。我会为 Builder...build() 部分设置一行,然后将其他参数设置在十个单独的行上? :-/
    猜你喜欢
    • 2020-02-16
    • 1970-01-01
    • 2020-08-31
    • 1970-01-01
    • 2016-12-10
    • 1970-01-01
    • 2020-01-31
    • 1970-01-01
    • 2020-07-18
    相关资源
    最近更新 更多