具有元素的条件包含的生成器

2022-09-02 04:41:56

我一直想知道是否可以更优雅地使用可选参数来做Builder:

我有什么:带有名称,id,年龄的对象。

我有包含年龄的复杂条件,我想在条件成功时将其发送给构建器,但我希望它具有优雅的一个衬里和一个参数。

到目前为止,我拥有什么:

 Builder.name("name").id("id").age(age, complexCondition).build();

 Builder builder = Builder.name("name").id("id");
 if(complexCondition){
     builder.age(age);
 }

有没有更好的选择?我想解决我拥有它的情况,而无需过度工程构建器,并且不会对每个复杂的条件检查进行过度编码。

upd:我正在寻找的是没有以下解决方案的解决方案:

a)将复杂的检查或布尔值传递给构建者 - 而不是他的工作来检查定义

b) 无需在调用 builder 的方法中为每个条件检查添加 3 行


答案 1

我的答案是保持简单。构建器的责任是构建对象。不要提供复杂的DSL来评估条件。所以你的第二个片段是完全没问题的。

要避免使用许多与对生成器的调用交错的检查来重载代码,您需要做的就是将这些检查的代码提取到方法中。所以你可以从if

Builder builder = Builder.name("name").id("id");
if (complexCondition) {
    builder.age(age);
}

Integer age = null; // or whatever other default value you want
if (complexCondition) {
    age = somethingElse;
}
Builder builder = Builder.name("name").id("id").age(age);

最后,bu提取4条第一行到一个方法计算并返回年龄,

Builder builder = Builder.name("name").id("id").age(computeAge());

我个人更喜欢它缩进以下方式,IMO使它更具可读性,更易于调试:

Builder builder = Builder.name("name")
                         .id("id")
                         .age(computeAge());

答案 2

好吧,如果你想要每个方法调用一个参数,你可以拆分

Builder.name("name").id("id").age(age, complexCondition).build();

Builder.name("name").id("id").age(age).ageCondition(complexCondition).build();

您可能需要考虑创建一个(其中是用于评估条件的某种类型的实例)。这样,当您调用 的 时,只有在提供 age 参数时,您才计算复杂条件。complexConditionPredicate<Something>SomethingBuilderbuild()

该方法可以如下所示:build

public SomeClass build() {
    SomeClass obj = new SomeClass();
    obj.setName(name);
    if (age != null && someCondition != null && someCondition.test(something)) {
        obj.setAge(age);
    }
    return obj;
}

我不确定会是什么。这取决于你复杂状况的性质。something

或者,如果您希望条件是可选的:

public SomeClass build() {
    SomeClass obj = new SomeClass();
    obj.setName(name);
    if (age != null) {
        if (someCondition != null)) {
            if (someCondition.test(something)) {
                obj.setAge(age);
            }
        } else {
            obj.setAge(age);
        }
    }
    return obj;
}

推荐