오늘 공부한 내용
- 코드카타 2문제
- Spring 심화 프로젝트 작성
새로 알게된점
@Builder
빌더 패턴 (Builder patter) 이란?
복잡한 Object들을 단계별로 구축할 수 있는 생성 디자인 패턴을 말하며 이 패턴을 사용하면, 동일한 구성코드를 사용하여 다양한 타입과 표현을 제공한다.
일반적으로 객체를 정의하고 그 객체를 생성할 때 보통 생성자를 통해 생성하는 것을 생각한다.
Bag bag = new Bag("name", 1000, "memo");
하지만 생성자를 통해 객체를 생성하는데 몇 가지 단점이 있기에 빌더패턴으로 작성시 이를 보완할수 있다.
Bag bag = Bag.builder()
.name("name")
.money(1000)
.memo("memo")
.build();
객체를 생성할 수 있는 빌더를 builder() 함수를 통해 얻고 거기에 셋팅하고자 하는 값을 셋팅하고 마지막에 build()를 통해 빌더를 작동 시켜 객체를 생성한다.
빌더를 사용하는 이유
- 뛰어난 가독성을 가지고 있다.
생성자 파라미터가 많을 경우 가독성이 좋지 않다.
예시로 위에 작성했던 생성자 파라미터가 3개가 아닌 7~8개가 되면 어떻게 될까?
Bag bag = new Bag("name", 1000, "memo", "abc", "what", "is", "it", "?");
이렇게 작성될시 각 값들이 어떤 값을 의미하는지 이해하기 힘들 것이다.
하지만 빌더 패턴으로 구현하면 각 값들이 빌더의 각 값들의 이름 함수로 셋팅되어 각각 무슨 값을 의미하는기 파악하기 쉬워지며 가독성이 높아지고 추후 같은 타입의 다른 변수의 값을 서로 바꿔 넣는 것을 방지 할 수도 있다
Bag bag = Bag.builder()
.name("name")
.money(1000)
.memo("memo")
.letter("This is the letter")
.box("This is the box")
.build();
- 데이터의 순서에 상관없이 객체 성성이 가능하다.
생성자의 경우는 정해진 파라미터 순서대로 꼭 값을 넣어줘야한다. 순서를 무시하고 값을 넣으면 에러가 발생하거나 엉뚱한데 값이 들어갈 수 있다.
public Bag(String name, int money, String memo) {
this.name = name;
this.money = money;
this.memo = memo;
}
하지만 빌더 패턴은 빌더의 필드 이름으로 값을 설정하기 때문에 순서에 종속적이지 않다.
그냥 쓰이는 곳에서 어떤 필드를 먼저 설정해야하는지 굳이 순서를 생각할 필요 없이 편하게 설정하면 된다.
Bag bag = Bag.builder()
.name("name")
.memo("memo") // memo를 money 대신 먼저!
.money(1000)
.build();
추가적인 장점으로
- 불필요한 생성자의 제거
- setter 메서드가 없으므로 변경 불가능한 객체를 만들수 있다. (객체불변성)
- 한번에 객체를 생성하므로 객체 일관성이 깨지지 않는다.
빌더는 사용하는 방법으로 다음과 같이 만들어진다.
- Member 클래스 내부에 빌더클래스 생성.
- 각 멤버 변수별 메서드를 작성, 각 메소드는 변수에 값을 set하고 빌더객체를 리턴한다.
- build() 메서드는 필수 멤버변수의 null체크를 하고 지금까지 set된 builder를 바탕으로 Member 클래스의 생성자를 호출하고 인스턴스를 리턴.
public class Member {
private String nickname; //필수
private String password; //필수
private Gender gender; //선택
public static class Builder {
private final String nickname;
private final String password;
private Gender gender;
// 필수변수는 생성자로 값을 넣는다.
public Builder(String nickname, String password) {
this.nickname = nickname;
this.password = password;
}
// 멤버변수별 메소드: 빌더클래스의 필드값을 set하고 빌더객체를 리턴한다.
public Builder gender(Gender gender) {
this.gender = gender;
return this;
}
// 빌더메소드
public Member build() {
return new Member(this);
}
}
public Member(Builder builder) {
this.nickname = builder.nickname;
this.password = builder.password;
this.gender = builder.gender;
}
}
Member memberEntity = new Builder("minji", "1234")
.gender(Gender.F)
.build();
하지만 빌더 패턴도 역시 단점이 존재한다. 객체를 생성하려면 우선 빌더객체를 생성해야 하고, 보다시피 다른 패턴들보다 많은 코드를 요구하기 때문에 인자가 충분히 많은 상황에서 이용할 필요가 있다.
아니면 @Builder 을 이용하여 빌더클래스를 직접 만들지 않고 어노테이션 하나로 클래스를 생성할 수 있다.
클래스 또는 생성자 위에 @Builder 어노테이션을 붙여주면 빌더패턴 코드가 빌드된다.
생성자 상단에 선언시 생성자에 포함된 필드만 빌더에 포함된다.
- 클래스 전체 Builder 적용
@Getter @Builder // ✨ 클래스 전체 필드를 빌더로 사용 가능!
public class UserLombok {
private Long id;
private String email;
private String password;
private String name;
}
// 사용예제
public User join(String email, String password, String name) {
UserLombok build = UserLombok.builder()
.email(email)
.password(password)
.name(name)
.build();
...
}
- 특정 생성자에서만 Builder 적용 가능
@Getter
public class UserLombok {
private Long id;
private String email;
private String password;
private String name;
public UserLombok(Long id, String email, String password, String name) {
this.id = id;
this.email = email;
this.password = password;
this.name = name;
}
@Builder // ✨ 빌더는 email, password만 사용 가능
public UserLombok(String email, String password) {
this.email = email;
this.password = password;
}
}
// 사용예제 - email, password만 가능!
public User join(String email, String password, String name) {
UserLombok build = UserLombok.builder()
.email(email)
.password(password)
.build();
...
}
'개발자 일지 > TIL' 카테고리의 다른 글
스파르타 내일배움캠프 90일차 240103 / KPT (1) | 2024.01.06 |
---|---|
스파르타 내일배움캠프 89일차 240102 / Swagger-UI 사용 (0) | 2024.01.02 |
스파르타 내일배움캠프 84일차 231227 (0) | 2023.12.29 |
스파르타 내일배움캠프 83일차 231226 / 심화프로젝트 시작 (0) | 2023.12.26 |
스파르타 내일배움캠프 79일차 231222 (0) | 2023.12.26 |