Java BuilderTestPattern - 如何避免样板?

sln*_*wak 8 java builder boilerplate bytecode-manipulation lombok

我的项目中有很多值对象.

我正在使用项目lombok来消除一些样板,所以我的值对象看起来像下面这样:

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

    private final String firstProp;
    private final int secondProp;   

}
Run Code Online (Sandbox Code Playgroud)

不错,几乎没有样板.

现在,我在测试中经常使用all-args构造函数.它看起来很乱,所以我想我会介绍Builder Pattern变种:

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
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

现在代码看起来很不错:

ValueObjectBuilder
.newValueObject()
.withFirstProp("prop")
.withSecondProp(15)
.build();
Run Code Online (Sandbox Code Playgroud)

现在,问题是 - 正如我所提到的,我必须编写很多类似的类......我已经厌倦了复制粘贴它们.

我正在寻找的是一个黑魔法智能工具,它将以某种方式为我生成这个代码.

我知道,@Builder龙目岛有一个注释,但它不符合我的要求.原因如下:

1)我无法在lombok的Builder中提供默认值.嗯,实际上,有可能 - 通过自己实现构建器类模板

@Builder
public class Foo {
    private String prop;

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

}
Run Code Online (Sandbox Code Playgroud)

这也会产生一些样板.

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

3)最重要的原因:我不是在创造一个"自然"的建设者.据我所知,lombok旨在为给定的带注释的类创建Builder - 我不知道是否有办法从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);
    }
}
Run Code Online (Sandbox Code Playgroud)

干杯,Slawek

mik*_*kea 5

我知道这是旧的,但如果有其他人遇到这个,我找到了另一种解决方案,为构建器提供默认值.

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

@Builder
public class Foo {
    private String prop;

    public static FooBuilder builder() {
        return new FooBuilder().prop("def value");
    }
}
Run Code Online (Sandbox Code Playgroud)

它不是一个理想的解决方案,但是必须覆盖整个构建器本身或者有一个自定义构造函数(如果有很多变量,这是很痛苦的恕我直言.拥有@With或@Default的东西仍然会很好用于处理此问题的注释.


uni*_*eek 1

尝试使用Bob-the-builder来构建 Eclipse。嗯..我想如果你碰巧使用 eclipse 的话效果最好!如果您不使用 eclipse,这里链接的页面底部提到了一些可能有用的相关项目。