我一直想知道可以更优雅地使用可选参数做Builder:
我拥有的:具有名称,身份,年龄的对象。
我有复杂的条件包括年龄,我想在成功的条件下发送给建设者,但我想让它优雅的一个衬垫与一个参数。
到目前为止我有什么:
Builder.name("name").id("id").age(age, complexCondition).build();
要么
Builder builder = Builder.name("name").id("id");
if(complexCondition){
builder.age(age);
}
还有更好的选择吗?我想解决条件,我没有过度工程建设者,没有过度编码的每一个复杂的条件检查。
upd:我正在寻找的解决方案是:
a)将complexChecks或booleans传递给构建者 - 而不是按照定义检查他的工作
b)每个条件不添加3行检查调用构建器的方法内部
我的答案是保持简单。构建器的职责是构建对象。不提供复杂的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);
最后,将4个第一行提取到计算并返回年龄的方法中
Builder builder = Builder.name("name").id("id").age(computeAge());
我个人更喜欢它以下面的方式缩进,IMO使它更易读和更容易调试:
Builder builder = Builder.name("name")
.id("id")
.age(computeAge());
好吧,如果你想为每个方法调用一个参数,你可以拆分
Builder.name("name").id("id").age(age, complexCondition).build();
成
Builder.name("name").id("id").age(age).ageCondition(complexCondition).build();
您可能需要考虑将complexCondition
设为Predicate<Something>
(其中Something
是用于评估条件的某种类型的实例)。这样,当您调用Builder
的build()
时,如果提供了age参数,则只评估复杂条件。
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;
}
警告!大多数构建器都要求您重新分配构建器变量。你下面的例子会给你带来麻烦。
Builder builder = Builder.name("name").id("id");
if(complexCondition){
builder.age(age);
}
你应该习惯这种格式。
Builder builder = Builder.name("name").id("id");
if(complexCondition){
builder = builder.age(age);
}