Reputation: 53
Im having difficulties to figure out how to change some field in a object created by builder pattern: for example this is the class
public class Pizza {
private int size;
private boolean cheese;
private boolean pepperoni;
private boolean bacon;
public static class Builder {
//required
private final int size;
//optional
private boolean cheese = false;
private boolean pepperoni = false;
private boolean bacon = false;
public Builder(int size) {
this.size = size;
}
public Builder cheese(boolean value) {
cheese = value;
return this;
}
public Builder pepperoni(boolean value) {
pepperoni = value;
return this;
}
public Builder bacon(boolean value) {
bacon = value;
return this;
}
public Pizza build() {
return new Pizza(this);
}
}
private Pizza(Builder builder) {
size = builder.size;
cheese = builder.cheese;
pepperoni = builder.pepperoni;
bacon = builder.bacon;
}
}
and Pizza obect is created like this:
Pizza pizza = new Pizza.Builder(12)
.cheese(true)
.pepperoni(true)
.bacon(true)
.build();
now what I'm trying to find out is how to change in this object for example cheese field to false? I don't have getters and setters, I know I can use reflection but it makes code harder to read and understand. So is builder pattern useful to not final objects ?
Upvotes: 1
Views: 13441
Reputation: 774
The best way is to use Lombok's @Builder
annotation.
And you need to specify (toBuilder = true)
to be able to convert the object back to the builder and modify the field.
@Builder(toBuilder = true)
public class Pizza {
...
}
Pizza pizza = Pizza.builder()
.cheese(true)
.pepperoni(true)
.bacon(true)
.build();
And now you want to modify one field - super easy!
Pizza modifiedPizza = pizza.toBuilder()
.cheese(false)
.build();
Upvotes: 2
Reputation: 1112
Builder class should have methods to set the optional parameters and it should return the same Builder object after setting the optional attribute. As "cheese" is your optional parameter so you need a setter for it in your Builder class
public Builder cheese(Boolean cheese) {
this.cheese = cheese;
return this;
}
Then you can use :
Pizza pizza1 = new Pizza.Builder(12)
.cheese(false)
.pepperoni(true)
.bacon(true)
.build();
Upvotes: 0
Reputation: 7828
how to change in this object for example cheese field to false?
You should add a setter
to the Pizza
as:
class Pizza {
//...
public void setCheese(boolean cheese) {
this.cheese = cheese;
}
@Override
public String toString() {
return String.format("cheese: %s", this.cheese);
}
//...
}
And then you can use it as:
System.out.println(pizza);
pizza.setCheese(false);
System.out.println(pizza);
After your initialization, the output:
cheese: true
cheese: false
So is builder pattern useful to not final objects ?
There are some interesting posts discussing Builder Pattern
: Three Reasons Why I Like the Builder Pattern and When would you use the Builder Pattern?.
Personally, I would say it quite depends on your case itself.
Upvotes: 3
Reputation: 2683
The builder pattern is usually good to create immutable objects but it does not need to do so. If you'd like to be able to change values after build
, you just need to add a setter for that.
Upvotes: 4