GoF 디자인 패턴(Design Pattern)이란?
Builder Pattern
생성 패턴 중 하나로, 객체의 생성과 표현을 분리해 객체를 생성하는 패턴
언제 사용하나요 ?
기존 객체 생성 방법 2가지
생성자 유무에 따른 빌더 작동 방식
•
생성자가 없는 경우 : 모든 멤버 변수를 파라미터로 받는 기본 생성자 생성
•
생성자가 있을 경우 : 따로 생성자를 생성하지 않음
실전
@Getter
@Setter // 문제 1
@NoArgsConstructor // 문제 2
@AllArgsConstructor // 문제 3
@Builder // 고려해야할것
@Entity
public class Posts
Java
복사
문제
@Setter 사용
Setter는 객체를 언제든지 변경할 수 있다. 그래서 객체의 안정성이 보장받기는 힘들다.
특히 엔티티에서는 어디서 누구에의해 객체가 변경되었는지 추적하는 것이 힘듦.
—> 값 변경이 필요할 때는 의미있는 메서드를 생성하여 사용하는 것이 좋다.
문제
@NoArgsConstructor
Entity 클래스 인스턴스 변수는 직접 접근이 아닌 내부 메소드로 접근해야한다.(Getter) 왜냐하면 JPA는 기본적으로 Entity에 접근하는것이 아니라 Entity proxy에 접근하게 되어있다. (프록시 ..?)
기본생성자의 접근제어는 활용하면 더 좋은 방향으로 사용할 수 있다.
@NoArgsConstructor(access = AccessLevel.PROTECTED)
—> 무분별하게 객체를 만들지 않는다 = 의미없는 객체를 만들지 않는다
문제
@AllArgsConstructor
우선 @Build를 사용하는 방법은 두 가지가 있다.
1.
클래스에 사용하는법
2.
생성자함수 위에서 사용하는법
문제1번처럼 @Build와 @NoArgsConstructor을 같이사용하면 당연히 오류가 발생합니다.(빌더를 알고, NoArgsConstructor을 이해하고 있다면 생각해볼만한 내용) 이를 해결하려면 @AllArgsConstructor을 같이 써주어야 합니다.
하지만 @AllArgsConstructor은 위험합니다
클래스에 존재하는 모든 필드변수를 포함한 생성자를 자동으로 생성하는데, 변수의 선언 순서(=위치)에 영향을 받게 된다. 만약 변수 선언 위치가 달라진다면 이것도 오류로 이어질 것이다.
그래서 2번의 방식을 추구해야한다.
이를 바탕으로 리팩토링 한다면
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class Posts {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
private String content;
private String writer;
private Integer viewCount;
@Embedded
private Period period;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;
@Builder
public Posts(Long id, String title, String content, String writer, Integer viewCount, Period period) {
this.id = id;
this.title = title;
this.content = content;
this.writer = writer;
this.viewCount = viewCount;
this.period = period;
}
}
Java
복사