Java BuilderTestPattern - 如何避免样板代码?

8

我在我的项目中有很多值对象。

我正在使用Project Lombok来消除一些模板代码,因此我的值对象看起来像以下这个:

@Value
@Accessors(fluent = true)
public class ValueObject {

    private final String firstProp;
    private final int secondProp;   

}

还不错,几乎没有样板代码。

现在,在我的测试中经常使用全参构造函数。这看起来有点杂乱,所以我想介绍建造者模式的变体:

public class ValueObjectBuilder {

    private static final int DEFAULT_VALUE_FOR_SECOND_PROP = 666;

    private String firstProp = "default value for first prop;
    private int secondProp = DEFAULT_VALUE_FOR_SECOND_PROP;

    private ValueObjectBuilder() {}

    public static ValueObjectBuilder newValueObject() {
        return new ValueObjectBuilder();
    }

    public ValueObjectBuilder withFirstProp(String firstProp) {
        this.firstProp = firstProp
        return this;
    }

    public ValueObjectBuilder withFirstProp(int secondProp) {
        this.secondProp = secondProp;
        return this;
    }

    public ValueObject build() {
        return new ValueObject(
                firstProp, secondProp
        );
    }
}

现在代码看起来非常不错:

ValueObjectBuilder
.newValueObject()
.withFirstProp("prop")
.withSecondProp(15)
.build();

现在的问题是 - 正如我所提到的,我必须写很多类似的类... 我已经厌倦了复制粘贴它们。
我正在寻找的是一种黑魔法智能工具,它将以某种方式为我生成这段代码。
我知道,在Lombok中有一个@Builder注释,但它不符合我的要求。原因如下:
1) 我无法在lombok的Builder中提供默认值。好吧,实际上,这是可能的 - 通过自己实现builder类模板
@Builder
public class Foo {
    private String prop;

    public static class FooBuilder() {
        private String prop = "def value";
        ...
    }

}

1)它还生成了一些样板代码。

2)我找不到任何方法在lombok的构建器中为每个字段访问器添加前缀。也许@Wither可以帮助这里?但是我不知道如何正确使用它。

3)最重要的原因:我并没有创建一个“自然”的构建器。据我所知,lombok旨在为给定的注释类创建构建器-我不知道是否有一种方法可以从build()方法中返回任何其他对象。

那么,总结一下:您知道任何可能帮助我的工具吗?或者也许所有我提到的事情实际上都可以使用Lombok实现?

编辑

好的,所以我可能找到了一个解决这个特殊情况的解决方案。使用lombok,我们可以使用:

@Setter
@Accessors(chain = true, fluent = true)
@NoArgsConstructor(staticName = "newValueObject")
public class ValueObjectBuilder {
    private String firstProp = "default";
    private int secondProp = 666;

    public ValueObject build() {
        return new ValueObject(firstProp, secondProp);
    }
}

您好,Slawek先生:

2个回答

5

我知道这已经有些陈旧了,但如果有其他人遇到了相似的问题,我发现提供构建器的默认值有一种替代方案。

重写构建器方法,在返回构建器之前提供默认值。所以在上面的例子中:

@Builder
public class Foo {
    private String prop;

    public static FooBuilder builder() {
        return new FooBuilder().prop("def value");
    }
}

这并不是一种理想的解决方案,但比覆盖整个构建器或使用自定义构造函数要好(如果有很多变量,则我认为这很痛苦)。如果有类似于@With或@Default注释来处理这个问题仍然是很好的。


谢谢,我稍后会查看! - slnowak
1
@mikea 你用的是哪个版本?我正在尝试,但是收到了编译错误 FooBuilder 不是公共的,无法从包外访问 - nKognito
1
该死,我使用了IntelliJ插件.. 这是一个问题。 - nKognito
@slnowak 不,它不会。 - nKognito

1

尝试在eclipse中使用Bob-the-builder。嗯...我想如果你正在使用eclipse,那么这可能是最好的选择!如果你没有使用eclipse,在此链接页面底部提到了几个相关项目,可能会有用。


谢谢。首先,我正在使用IDEA - 你试过其中之一吗?其次,我实际上正在寻找一些能够像lombok一样生成我的代码的工具 - 没有那些混乱。 - slnowak
很遗憾,我没有。我听说 IDEA 很棒,我相信这一点,因为我以前用过 RubyMine,对于 Ruby 工作来说非常棒!我知道这些生成器不像 Lombok 那样流畅...(删除并更正了 Lombok 的拼写!) - unigeek

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