This is the 11th day of my participation in the August More Text Challenge
preface
In the previous section we discussed the advantages and disadvantages of using a static factory approach instead of a constructor. In this section we discuss what to do when multiple constructor parameters are present. Static factories and constructors have a common limitation in that they do not scale well to a large number of optional parameters.
Inelegant method
Use the overlapping constructor pattern
For classes with multiple optional parameters, some people use the overlapping constructor pattern. Provide a constructor with only required arguments, a second constructor with one optional argument, a third with two, and so on. The problem is that too many parameters of the constructor make it difficult to write and read the client code. Although IDEA can help us to prompt the corresponding attribute names and parameters, it is too time-consuming and easy to make mistakes. For example, if we reverse two arguments of the same type, the compiler will not report an error, but there is already a problem.
Use JavaBeans patterns
That is, the no-argument constructor is called to create the object, and then setter methods are called to set each required parameter, along with each associated optional parameter. This is also the method I usually use, to be honest, I think this is not a problem, otherwise how to deal with the problem of filling data. But we do have some of the problems mentioned in the book where an error occurs in the middle of an object creation that doesn’t match our expectations.
The elegant way
Use the Builder method to build objects
public class Article {
private Integer articleId;
private String title;
private Integer categoryId;
public static class Builder {
private String title;
private Integer categoryId;
private Integer articleId = Integer.valueOf(0);
public Builder(String title, Integer categoryId) {
this.title = title;
this.categoryId = categoryId;
}
public Builder articleId(Integer articleId) {
this.articleId = articleId;
return this;
}
public Article build(a){
return new Article(this); }}private Article(Builder builder) {
this.articleId = builder.articleId;
this.title = builder.title;
this.categoryId = builder.categoryId;
}
}
Article article =new Article.Builder("Create and destroy objects - Consider using constructors when encountering multiple constructor arguments.".15)
.articleId(0).build();
Copy the code
While it’s easy to read, writing Builder is a bit of a chore. You can use Lombok’s @Builder annotation to generate the corresponding Builder method directly.
@Builder(toBuilder = true)
@Getter
public class Author {
@Builder.Default
private String userName = "Temporary camp";
private String company;
private Integer age;
@Singular("addArticle")
private List<Article> articleList;
}
List<Article> articleList =new ArrayList<>();
articleList.add(article);
Author author = Author.builder().userName("Temporary camp")
.articleList(articleList)
.addArticle(article).build();
author.getArticleList();
Copy the code
@Builder declares entities, indicating that they can be initialized in Builder mode, and @getter annotation, indicating that only getters are exposed and all setters for properties are closed, i.e. private decoration
To set Default values for properties, use the @Builder.Default annotation,
Add @singular annotation to List in entity class. Note addArticle after that, which means we can use this method to add a single entity to and from List
ArticleList (articleList) and addArticle(article) will work
Note that there is a difference between the call methods we generate using Lombok and those we write ourselves.
The object creation work provides the Builder method, which provides in the design of data entities, external keep private setter, and the assignment of attributes using the Builder method, this way is the most elegant, but also more in line with the principle of encapsulation, do not publicly write properties!
The Builder mode can constrain its parameters, the Build method can verify these constraints, copy the parameters from the Builder into the object, and verify them in the object domain instead of the Builder domain. If any of the constraints are violated, The build method should throw an IllegalStateException. The Builder pattern is flexible enough to build multiple objects from a single Builder. The only downside is that in order to create an object, you must first create an intermediate object, and the Builder pattern also makes the construction process more verbose.
conclusion
If there are more than one optional parameter in the class, the Builder mode is a good choice for designing the class and is much more readable than the original method.