在做学习项目时了解到了Lombok的@Builder注解和建造者模式,现在将这两个知识点做一个简单的记录
建造者模式
我们首先来看看定义:
将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示
什么意思?我们不妨先来看一个场景:
当一个复杂对象(构造函数中参数大于4个)被构建时,我们会怎么做呢?
方法一:
public class BookCommentRespDto{
private Long commentTotal;
private Long id;
private String commentContent;
private String commentUser;
private Long commentUserId;
private String commentUserPhoto;
private LocalDateTime commentTime;
.....
/*折叠构造函数模式*/
public BookCommentRespDto(Long commentUserId, String commentContent){
this.commentUserId = commentUserId;
this.commentContent = commentContent;
}
public BookCommentRespDto(Long commentUserId, String commentContent, String commentUserPhoto){
this.commentUserId = commentUserId;
this.commentContent = commentContent;
this.commentUserPhoto = commentUserPhoto;
}
public BookCommentRespDto(Long commentUserId, String commentContent, String commentUserPhoto, List<CommentInfo> comments){
this.commentUserId = commentUserId;
this.commentContent = commentContent;
this.commentUserPhoto = commentUserPhoto;
this.comments = comments;
}
....
}
这种方法十分常见且简单。但也有一个显而易见的问题,太过繁琐,可读性差,参数的含义和选择上会对开发者造成障碍。
那么第二种方法如何?
/*JavaBean方式*/
public Long getCommentTotal() {
return commentTotal;
}
public void setCommentTotal(Long commentTotal) {
this.commentTotal = commentTotal;
}
public List<CommentInfo> getComments() {
return comments;
}
public void setComments(List<CommentInfo> comments) {
this.comments = comments;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getCommentContent() {
return commentContent;
}
public void setCommentContent(String commentContent) {
this.commentContent = commentContent;
}
public String getCommentUser() {
return commentUser;
}
public void setCommentUser(String commentUser) {
this.commentUser = commentUser;
}
public Long getCommentUserId() {
return commentUserId;
}
public void setCommentUserId(Long commentUserId) {
this.commentUserId = commentUserId;
}
....
这种方法一目了然,但由于对象的属性是分步设置,有可能会因为程序员的疏忽导致漏了值或者状态变化而出错。
而建造者模式就是为解决这个问题而诞生的!
建造者模式
抛开复杂的定义,我觉得这说白了就一句话:一步步建造对象
因为我使用了Lombok,我就直接引用不用Lombok该怎么做的思路就行
- 在BookCommentRespDto中创建一个静态内部类 Builder,然后将BookCommentRespDto 中的参数都复制到Builder类中。
- 在BookCommentRespDto中创建一个private的构造函数,参数为Builder类型
- 在Builder中创建一个public的构造函数,参数为Computer中必填的那些参数
- 在Builder中创建设置函数,对BookCommentRespDto中那些可选参数进行赋值,返回值为Builder类型的实例
- 在Builder中创建一个build()方法,在其中构建BookCommentRespDto的实例并返回
使用Lombok并且优化后的代码后
@Data
@Builder
public class BookCommentRespDto {
@Schema(description = "评论总数")
private Long commentTotal;
@Schema(description = "评论列表")
private List<CommentInfo> comments;
@Data
@Builder
public static class CommentInfo {
@Schema(description = "评论ID")
private Long id;
@Schema(description = "评论内容")
private String commentContent;
@Schema(description = "评论用户")
@JsonSerialize(using = UsernameSerializer.class)
private String commentUser;
@Schema(description = "评论用户ID")
private Long commentUserId;
@Schema(description = "评论用户头像")
private String commentUserPhoto;
@Schema(description = "评论时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime commentTime;
}
}
使用方法
BookCommentRespDto bookCommentRespDto = BookCommentRespDto.builder()
.commentTotal(commentTotal).build();
@Builder 属性介绍
- @Builder.Default:非 final 的字段可以有默认值
- builderMethodName:指定创建内部静态类的方法名,默认值为 builder
- buildMethodName:指定创建实体类的方法名,默认值为 build
- builderClassName:指定内部静态的类名,默认值为 “”,默认创建的类名为 thisclassBuilder
- toBuilder:设置为 true 可以对这个对象进行拷贝生成新的对象,可以再修改,默认为 false
- access:设置 builderMethodName 的访问权限修饰符,默认为 public
共有 PUBLIC、MODULE、PROTECTED、PACKAGE、PRIVATE,其中 MODULE 是 Java 9 的新特性 - setterPrefix:设置 setter 方法的前缀,默认为 “”