1 回答

TA貢獻1864條經驗 獲得超2個贊
在我看來,從風格/設計的角度來看,您的方法沒有根本性的錯誤。但是,正如用戶 JB Nizet 在評論中所解釋的那樣,存在兩個主要問題:
您會遇到維護問題,因為您必須復制每個外部構建器方法。(Lombok
@Delegate
在這里幫不了你,因為它對 Lombok 本身生成的類不起作用。)您的構建器的用戶可以同時調用
dimensions(Dimensions)
委托方法和委托方法,這非常令人困惑。
從用戶的角度來看,我希望這樣使用構建器:
Dragon dragon = Dragon.builder()
.dimensions()
.height(12.0)
.length(25.0)
.back()
.name("Smaug")
.build();
這是實現它的方法(使用 Lombok 1.18.8):
@Builder
public class Dragon {
private Dimensions dimensions;
private String name;
public static class DragonBuilder {
private Dimensions.DimensionsBuilder innerBuilder =
new Dimensions.DimensionsBuilder(this);
// If a method of the same name exists, Lombok does not generate
// another one even if the parameters differ.
// In this way, users cannot set their own dimensions object.
public Dimensions.DimensionsBuilder dimensions() {
return innerBuilder;
}
// Customize build() so that your innerBuilder is used to create
// the Dimensions instance.
public Dragon build() {
return new Dragon(innerBuilder.build(), name);
}
}
}
的構建器Dimensions持有對容器的引用DragonBuilder:
// Don't let Lombok create a builder() method, so users cannot
// instantiate builders on their own.
@Builder(builderMethodName = "")
public class Dimensions {
private double height;
private double length;
public static class DimensionsBuilder {
private Dragon.DragonBuilder parentBuilder;
// The only constructor takes a reference to the containing builder.
DimensionsBuilder(Dragon.DragonBuilder parentBuilder) {
this.parentBuilder = parentBuilder;
}
// Provide a method that returns the containing builder.
public Dragon.DragonBuilder back() {
return parentBuilder;
}
// The build() method should not be called directly, so
// we make it package-private.
Dimensions build() {
return new Dimensions(height, length);
}
}
}
這種方法可以擴展,因為 Lombok 會自動在構建器中生成所有必要的剩余 setter 方法。此外,由于用戶提供了自己的Dimensions實例,因此可能不會出現意外。(你可以允許這樣做,但我強烈建議對潛在的沖突進行運行時檢查,例如檢查是否已調用這兩種方法。)
缺點是它Dimensions.builder()不再可用,因此不能直接使用或在其他具有Dimensions字段的類的構建器中使用。但是,也有一個解決方案:使用@SuperBuilder Dimensions并定義一個class NestedDimensionsBuilder extends Dimensions.DimensionsBuilder<Dimensions, NestedDimensionsBuilder>within DragonBuilder。
添加回答
舉報