问题
Which of the following is the better approach to implement the builder pattern?
1) Using the object to build instead of all its properties in the builder (and create it in the builder constructor):
public class Person {
private String firstName;
// other properties ...
private Person() {}
// getters ...
public static class Builder {
// person object instead of all the person properties
private Person person;
public Builder() {
person = new Person();
}
public Builder setFirstName(String firstName) {
person.firstName = firstName;
return this;
}
// other setters ...
public Person build() {
if (null == person.firstName) {
throw new IllegalStateException("Invalid data.");
}
return person;
}
}
}
2) Using the properties of the object to build instead of the object directly in the builder (and create it in the build() method):
public class Person {
private String firstName;
// other properties ...
private Person() {}
// getters ...
public static class Builder {
// person properties instead of object
private String firstName;
// other properties ...
public Builder() {}
public Builder setFirstName(String firstName) {
this.firstName = firstName;
return this;
}
// other setters ...
public Person build() {
if (null == this.firstName) {
throw new IllegalStateException("Invalid data.");
}
Person person = new Person();
person.firstName = firstName;
return person;
}
}
}
I prefer the first way because i think that with lots of properties repeat them in the builder is redundant. Are there some disadvantages with the first approach?
Thanks in advance and sorry for my bad english.
回答1:
Small Note : Yes the properties might be a repeat but they have advantages
Details below : If you look at the details here.
Pizza pizza = new Pizza(12);
pizza.setCheese(true);
pizza.setPepperoni(true);
pizza.setBacon(true);
The problem here is that because the object is created over several calls it may be in an inconsistent state partway through its construction. This also requires a lot of extra effort to ensure thread safety.
The better alternative is to use the Builder Pattern.
Notice below method in Builder and respective constructor or parent Pizza class - full code in link here
public static class Builder {
public Pizza build() { // Notice this method
return new Pizza(this);
}
}
private Pizza(Builder builder) { // Notice this Constructor
size = builder.size;
cheese = builder.cheese;
pepperoni = builder.pepperoni;
bacon = builder.bacon;
}
回答2:
The Builder
pattern has been described in the Gang of Four “Design Patterns” book that says:
The builder pattern is a design pattern that allows for the step-by-step creation of complex objects using the correct sequence of actions. The construction is controlled by a director object that only needs to know the type of object it is to create.
If there is a sequence of steps that needs to be followed while constructing the object then go for second option.
In your first option correct sequence of actions are not controlled. You can go for either option if sequence of actions are not defined.
回答3:
I think in your case there is no matter where to create the object. The builder would be used the same way in both cases with minimum difference in performance.
But if the object is immutable and it's field could be created with more than one step then I would certainly go with the second approach. For example you can check the source code of java.lang.StringBuilder
and see that the String
object is created in the last step:
public String toString() {
// Create a copy, don't share the array
return new String(value, 0, count);
}
Moreover I prefer the Wizard pattern. It is an extension of the Builder pattern which protects you from getting IllegalStateException.
public class Person {
private String firstName;
// other properties ...
private Person() {}
// getters ...
public static class Builder {
public Builder() {}
public FirstStep setFirstName(String firstName) {
return new FirstStep(firstName);
}
public static class FirstStep {
private String firstName;
private FirstStep(String firstName) {
this.firstName = firstName;
}
public Person build() {
Person person = new Person();
person.firstName = firstName;
return person;
}
}
}
}
来源:https://stackoverflow.com/questions/23169505/java-best-way-to-implement-builder-pattern