▶빌더패턴이 뭐지?
빌더패턴은 생성자로만 객체를 생성했을 때 문제를 해결하기 위한 패턴이다.
▶생성자로 객체 생성
생성자로만 객체 생성을 하면 코드가 복잡해지고 가독성이 떨어진다.
public class Person {
private String name;
private int age;
private String gender;
private String address;
public Person(String name, int age, String gender, String address) {
this.name = name;
this.age = age;
this.gender = gender;
this.address = address;
}
}
객체생성
Person person = new Person("John", 30, "Male", "123 Main St");
??? : "아 머가 먼지 모르겠네~~....해결할 수 없나? "
▶ Setter로 문제 해결
public class Person {
private String name;
private int age;
private String gender;
private String address;
public Person() {
// 기본 생성자
}
// Setter 메서드들
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setGender(String gender) {
this.gender = gender;
}
public void setAddress(String address) {
this.address = address;
}
}
객체 생성
Person person1 = new Person();
person1.setName("John");
person1.setAge(30);
person1.setGender("Male");
person1.setAddress("123 Main St");
??? :"오~ 아까보다 가독성이 좋아졌구만!!그리고 아까보다 유연하게 객체생성이 돼!"
하지만 이러한 방식은 불변성 유지가 어렵다.
Setter메서드는 객체를 처음 생성할 떄 필드값을 설정하기 위해 존재하는 메소드이다.
하지만 객체를 생성했음에도 여전히 외부적으로 Setter메소드를 노출하고 있으므로, 누군가가 Setter메소드를 호출해서 객체를 조작할수도 있다… ㄷㄷ
우리는 이것을 불변성을 보장할 수 없다고 이야기한다!!
해결할 수 없나? 왜 없겠는가
그래서 나온게 Builder패턴!!
▶Builder패턴으로 해결
Builder패턴 코드를 보기 전에 Builder 패턴으로 어떻게 객체를 생성하는지 코드를 보자.
Person person = new Person.Builder("John", 30)
.gender("Male")
.address("123 Main St")
.build();
앞에 이름와 나이는 필수 요소라고 하자.
그러면 요소에 이어서 .
을 붙여주고 값 입력
이어서 . 붙이고 값입력
한 후 .build() 통해서 객체를 생성할 수 있다.
Builder패턴의 코드는 이러하다.
public class Person {
private String name;
private int age;
private String gender;
private String address;
private Person(Builder builder) {
this.name = builder.name;
this.age = builder.age;
this.gender = builder.gender;
this.address = builder.address;
}
public static class Builder {
private String name;
private int age;
private String gender;
private String address;
public Builder(String name, int age) { //필수 요소들은 이렇게 코드 짬
this.name = name;
this.age = age;
}
public Builder gender(String gender) {
this.gender = gender;
return this;
}
public Builder address(String address) {
this.address = address;
return this;
}
public Person build() {
return new Person(this);
}
}
// Getter 메서드들 생략
}
이렇게 작성이 된다.
여기서 중요한것은 메소드의 리턴값이 빌더 객체 자신이라는 것이다.
그래야지 .을 붙여서 계속 이어갈 수 있다.
그 후 마지막단계로 빌더 클래스 내에 build()메소드를 정의하여서
최종생성된 결과를 제공한다.
그래!! 좋아!!...
builder패턴 좋아.. 좋긴한디…
근데 이거 누가 작성하고있음…
▶ Lombok의 @Builder
우리의 Lombok을 사용하면 그럴 필요가 없다고!!
import lombok.Builder;
@Builder
public class Person {
private String name;
private int age;
private String gender;
private String address;
}
// 사용 예시:
Person person = Person.builder()
.name("John")
.age(30)
.gender("Male")
.address("123 Main St")
.build();
@Builder 어노테이션 하나로
public class Person {
private String name;
private int age;
private String gender;
private String address;
private Person(Builder builder) {
this.name = builder.name;
this.age = builder.age;
this.gender = builder.gender;
this.address = builder.address;
}
public static class Builder {
private String name;
private int age;
private String gender;
private String address;
public Builder(String name, int age) {
this.name = name;
this.age = age;
}
public Builder gender(String gender) {
this.gender = gender;
return this;
}
public Builder address(String address) {
this.address = address;
return this;
}
public Person build() {
return new Person(this);
}
}
// Getter 메서드들 생략
}
이 코드를 작성하지 않아도 된다...!!
와우~~
▷ @Builder에서 필수요소 설정
import lombok.Builder;
import lombok.NonNull;
@Builder
public class Person {
@NonNull
private String name;
@NonNull
private int age;
private String gender;
private String address;
}
@NonNull 을 사용하면 해당 필드에 null 값을 허용하지 않도록 강제할 수 있다!