Lombok @Builder
- -
빌더 패턴
생성과 관련된 디자인 패턴으로, 다양한 구성의 인스턴스를 만드는 방법이다.
빌더 패턴은 싱글톤 패턴, 팩토리 패턴, 추상팩토리 패턴과 같이 생성패턴에 해당한다.
복잡한 객체를 생성하는 클래스와 표현하는 클래스를 분리하여, 동일한 절차에서도 서로 다른 표현을
생성하는 방법을 제공한다.
생성자만 사용할 때 발생할 수 있는 문제를 개선하기 위해 고안됐다.
빌더 패턴은 많은 Optional 한 멤버 변수(혹은 파라미터)나 지속성 없는 상태 값들에 대해 처리해야 하는
문제들을 해결합니다.
즉, 필수값과 필수값이 아닌 값들을 구분하기 위해서 사용한다.
예를들어, 팩토리 패턴이나 추상 팩토리 패턴에서는 생성해야하는 클래스에 대한 속성 값이 많을 때
아래와 같은 이슈들이 있습니다.
- 팩토리 클래스로 많은 파라미터를 넘겨줄 때 타입, 순서 등에 대한 관리가 어려워져 에러가 발생할 확률이 높아집니다.
- 경우에 따라 필요 없는 파라미터들에 대해서 팩토리 클래스에 일일이 NULL 값을 넘겨줘야 한다.
- 생성해야 하는 sub class가 무거워지고 복잡해짐에 따라 팩토리 클래스 또한 복잡해진다.
빌더패턴은 이러한 문제들을 해결하기 위해 별도의 Builder 클래스를 만들어 필수 값에 대해서는 생성자를 통해,
선택적인 값들에 대해서는 메소드를 통해 step-by-step으로 값을 입력받은 후에 build() 메소드를 통해
최종적으로 하나의 인스턴스를 리턴하는 방식이다.
빌드 패턴을 사용하는 이유
생성자 파라미터가 많을 경우 가독성이 좋지 않다.
클래스의 생성자 파라미터가 3개 이하일 경우에는 아래처럼 쉽게 생성할 수 있다.
하지만 생성자 파라미터가 많아진다면 생성하기가 까다로울 수 있다.
// User Class
public class User {
String name;
String phone;
String age;
public User(String name, String phone, String age){
this.name = name;
this.phone = phone;
this.age = age;
}
}
// User 객체 생성
User user = new User("obo", "010-4040-7902", "30")
// User 객체 생성(많은 경우)
User user = new User("obo", "010-4040-7902", "30", "20", "test", "10", "test2", ......)
객체 생성 시 값의 순서가 상관이 없다.
정해진 생성자를 통해 객체 생성 시 파라미터 순서가 정말 중요하다.
하지만 build 패턴을 사용하여 필드에 해당하는 메서드를 호출하여 설정하기 때문에 순서에 종속적이지 않다.
// User Class
public class User {
String name;
String phone;
Integer age;
public User(String name, String phone, Integer age){
this.name = name;
this.phone = phone;
this.age = age;
}
}
// 일반적인 생성자 User 객체 생성
// 생성자 파라미터 순서에 맞게 생성해야 한다.
User user = new User("obo", "010-4040-7902", 30);
// User Class (@Builder 어노테이션 사용)
public class User {
String name;
String phone;
Integer age;
@Builder
public User(String name, String phone, Integer age){
this.name = name;
this.phone = phone;
this.age = age;
}
}
// Build 패턴 객체 생성(Builder() 사용)
User user = User.builder()
.phone("010-4040-7902")
.age(30)
.name("obo")
.build();
아래의 예시를 확인합니다.
- 생성자 패턴
public class User {
private String name;
private String number;
private String address;
private String age;
public User(String name, String number){
this.name = name;
this.number = number;
}
public User(String name, String number, String address){
this.name = name;
this.number = number;
this.address = address;
}
public User(String name, String number, String address, String age){
this.name = name;
this.number = number;
this.address = address;
this.age = age;
}
}
위 코드는 생성자 패턴이다. setter 가 없으므로 변경할 수 없고, 새로운 값의 객체를 생성할때만 생성자를 통해
생성이 가능해 일관성과 불변성은 유지된다.
하지만 멤버변수가 하나만 늘어나도 코드의 작업량이 많아지고 가독성이 좋지 않다.
- Setter
public class User {
private String name;
private String number;
private String address;
private String age;
public User() {
}
public void setName(String name){
this.name = name;
}
public void setNumber(String number){
this.number = number;
}
public void setAddress(String address){
this.address = address;
}
public void setAge(String age){
this.age = age;
}
}
위처럼 기본 생성자를 사용하고 setter() 를 통해 필요한 값들을 지정한다면 코드 작업량이 줄고 가독성이 좋아진다.
하지만 객체의 일관성과 불변성이 깨진다.
이러한 문제를 해결하기 위해 빌더 패턴이 나왔다.
빌더패턴은 위 두개의 문제점을 없애고 장점을 결합한 패턴이다.
- 빌더 패턴
public class User {
private String name;
private String number;
private String address;
private String age;
public User() {
}
public static class Builder {
private String name;
private String number;
private String address;
private String age;
// 생성자로 설정할 시 필수로 입력해야 하는 필드로 구분된다.
// name 과 number 는 필수로 입력해야하는 필드다.
public Builder(String name, String number){
this.name = name;
this.number = number;
}
public Builder address(String address){
this.address = address;
return this;
}
public Builder age(String age){
this.age = age;
return this;
}
public User build() {
return new User(this);
}
}
}
위와 같이 빌더 패턴을 설정한다.
name 과 number 는 Builder() 에서 필수로 입력받아야 하는 값으로 생성자를 생성했다.
나머지 address 와 age 는 사용하지 않을시에는 설정을 안해도 된다.
아래와 같이 빌더 패턴을 사용하는 예시다.
User user = new User.Builder("obo", "010-1111-2222")
.address("서울특별시")
.build();
@Builder
위와 같이 빌더 패턴을 직접 구현해야하는 경우 복잡하다.
여기서 사용하는게 Lombok 라이브러리의 @Builder 어노테이션이다.
public class User {
private String name;
private String number;
private String address;
private String age;
@Builder
public User(String name, String number, String address){
this.name = name;
this.number = number;
this.address = address;
}
}
직접 구현할 필요없이 Lombok 의 @Builder 어노테이션을 통해 빌더 패턴을 구현할 수 있다.
'Java > Spring' 카테고리의 다른 글
Spring Boot Thymeleaf Dialect Layout 설정 (0) | 2022.10.06 |
---|---|
Jackson 라이브러리 ObjectMapper(readValue, writeValueAsString) (1) | 2022.09.21 |
JAR, WAR 차이점 및 특징 (0) | 2022.09.13 |
File.separator (0) | 2022.08.24 |
@Controller, @RestController (0) | 2022.08.09 |
소중한 공감 감사합니다