I've been wondering is possible to do Builder with optional parameters more elegantly:
what I have: Object with name, id, age.
I have complex condition for inclusion of age and I'd like to send it to builder on success of that condition but i'd like to have it elegant one liner with one parameter.
what i have so far:
Builder.name("name").id("id").age(age, complexCondition).build();
or
Builder builder = Builder.name("name").id("id");
if(complexCondition){
builder.age(age);
}
are there any better options? I'd like to resolve condition where I have it without over-engineering builder and without overcoding for every complex condition check.
upd: what I'm looking for is solution without:
a) passing complexChecks or booleans to builder -- not his job to check by definition
b) without adding 3 lines per condition check inside method that calls builder
My answer would be to keep it simple. The responsibility of a builder is to build an object. Not to provide a complex DSL to evaluate conditions. So your second snippet is perfectly fine.
All you need, to avoid overloading the code with many if
checks interlaced with calls to the builder is to extract the code of these checks to methods. So you can go from
Builder builder = Builder.name("name").id("id");
if (complexCondition) {
builder.age(age);
}
to
Integer age = null; // or whatever other default value you want
if (complexCondition) {
age = somethingElse;
}
Builder builder = Builder.name("name").id("id").age(age);
and finally, bu extracting the 4 first lines to a method computing and returning the age, to
Builder builder = Builder.name("name").id("id").age(computeAge());
I personally prefer it indented the following way, which, IMO, makes it more readable and easier to debug:
Builder builder = Builder.name("name")
.id("id")
.age(computeAge());
Well, if you want one argument per method call, you can split
Builder.name("name").id("id").age(age, complexCondition).build();
into
Builder.name("name").id("id").age(age).ageCondition(complexCondition).build();
You might want to consider making complexCondition
a Predicate<Something>
(where Something
is an instance of some type that is used to evaluate the condition). This way, when you call the Builder
's build()
, you only evaluate the complex condition if the age parameter was supplied.
The build
method can look like this:
public SomeClass build() {
SomeClass obj = new SomeClass();
obj.setName(name);
if (age != null && someCondition != null && someCondition.test(something)) {
obj.setAge(age);
}
return obj;
}
I'm not sure what something
would be. That depends on the nature of your complex condition.
Or, if you wish the condition to be optional:
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With