기록하는 공간
빌더 패턴(Builder Pattern)은 무엇인가 본문
빌더 패턴…
바로 예시부터 보면서 확인한다.
예시) 실제 사용 중인 코드
Board를 생성한다.
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Board {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "board_id")
@Schema(description = "아카이빙 Id", example = "1")
private Long boardId;
@Schema(description = "아카이빙 제목", example = "강아지와 산책한 날")
private String boardTitle;
@Schema(description = "추억의 날짜", example = "2023-11-14")
private String boardTime;
@Schema(description = "추억의 장소", example = "집 앞 공원")
private String boardPlace;
@Schema(description = "아카이빙 테그", example = "0")
private int boardTag;
@Schema(description = "아카이빙 내용", example = "아카이빙 내용")
private String boardContent;
@OneToMany(mappedBy = "board", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Comment> comments = new ArrayList<>();
@OneToMany(mappedBy = "board", cascade = CascadeType.ALL, orphanRemoval = true)
private List<MemberWriteBoard> memberWriteBoards = new ArrayList<>();
@Builder
private Board(String boardTitle, String boardPlace, int boardTag, String boardContent, String boardTime) {
this.boardTitle = boardTitle;
this.boardPlace = boardPlace;
this.boardTag = boardTag;
this.boardContent = boardContent;
this.boardTime = boardTime;
}
public static Board toEntity(BoardReqDto boardReqDto) {
return Board.builder()
.boardTitle(boardReqDto.boardTitle())
.boardTime(boardReqDto.boardTime())
.boardPlace(boardReqDto.boardPlace())
.boardTag(boardReqDto.boardTag())
.boardContent(boardReqDto.boardContent())
.build();
}
}
보시다시피 Board라는 객체는 생성자를 가질 것이다.
모든 필드를 가지는 생성자를 작성한다. 하지만 위의 코드를 기준으로 place가 필요 없거나, tag 등 일부 필드가 필요 없다면 어떻게 생성자를 만들까?
place가 필요 없는 경우
public Board(String boardTitle, int boardTag, String boardContent, String boardTime) {
this.boardTitle = boardTitle
this.boardTag = boardTag;
this.boardContent = boardContent;
this.boardTime = boardTime;
}
place와 tag가 필요 없는 경우
public Board(String boardTitle, String boardContent, String boardTime) {
this.boardTitle = boardTitle
this.boardContent = boardContent;
this.boardTime = boardTime;
}
이렇게 생성자를 오버로딩하는 방식을 사용할 것이다.
하지만 이러한 방식은 인스턴스 필드들이 많으면 많을수록 생성자에 들어갈 인자의 수가 늘어나 몇 번째 인자가 어떤 필드였는지 헷갈리는 경우가 생기게 된다.
위와 같은 경우 말고도 다양한 이유가 있다.
추가적으로 필드 값을 설정하기 위해 Setter를 사용할 수 있지만, 이는 불변성이 유지가 안되기 때문에 Setter 사용은 지양한다.
빌더를 사용하여 객체를 만들어 주기 위해서는 @Builder 어노테이션이 필요하다.
@Builder
public class Board {
.
.
.
}
위와같이 클래스 상단에 붙여도 되고,
아래와 같이 생성자에 붙여도 된다.
@Builder
private Board(String boardTitle, String boardPlace, int boardTag, String boardContent, String boardTime) {
this.boardTitle = boardTitle;
this.boardPlace = boardPlace;
this.boardTag = boardTag;
this.boardContent = boardContent;
this.boardTime = boardTime;
}
여기서 접근지정자는 pubilc과 private 모두 사용 가능한데.
public은 생성자 방식과 빌더 방식 두 가지로 객체 생성이 가능하니 더 많은 유연성을 제공한다.
private은 빌더 방식으로만 객체가 생성가능 하기 때문에, 불변성이 보장된다.
빌더 사용 예시
public static void main(String[] args) {
// 생성자 방식
Board boad1 = new Board(~~~~~~~~~~~~~~);
// 빌더 방식
Board board2 = Board.builder()
.boardTitle(~~~)
.boardPlace(~~~)
.boardTag(~~~)
.boardContent(~~~)
.boardTime(~~~)
.build();
}
이렇게 사용한다.
빌더 패턴 사용 이유
- 가독성 향상 : 많은 매개변수를 가진 생성자나 정적 팩토리 메서드를 사용하는 대신, 코드를 읽기 쉽게 만들 수 있다.
- 유연성 : 객체를 생성할 때 필요한 매개변수를 순서에 상관없이 설정할 수 있다. 또한, 필요한 매개변수만 설정하고, 나머지 매개 변수는 기본 값이나 선택적으로 값을 설정할 수 있다.
- 불변성 유지 : 모든 필드를 final로 선언하고, 객체 생성 후에는 변경할 수 없는 불변 객체를 만들 수 있다. 이는 다중 스레드 환경에서 객체의 안정성을 보장하며, 버그 발생 가능성을 줄인다.
- 객체 생성 과정의 로직 분리 : 객체를 생성하는 데 필요한 복잡한 로직이 있다면, 이 로직을 빌더 클래스에 구현함으로써 객체 클래스를 보다 깔끔하게 유지할 수 있다.
끝입니다.
'Spring' 카테고리의 다른 글
CSRF 방어 방법, 코드 (Security 사용 X) (0) | 2024.07.05 |
---|---|
NGINX로 Http, Https 적용하기 (0) | 2024.07.02 |
경로 매개변수(@PathVariable)와 쿼리 매개변수(@RequestParam) (0) | 2023.08.03 |
@ManyToMany를 사용하지 말자! (0) | 2023.07.26 |
intelliJ에서 Api통신을 해보자! (0) | 2023.07.20 |