1. 점층적 생성자 패턴
- 정적 팩토리와 생성자는 매개변수가 많을 경우 적절히 대응하기 어렵다.
- 과거에는 점층적 생성자 패턴 사용
public class Member {
private String name;
private String email;
private int age;
private String address;
private String phone;
public Member (String name, String email) {
this(name, email);
}
public Member (String name, String email, int age) {
this(name, email, age);
}
public Member (String name, String email, int age, String address) {
this(name, email, age, address);
}
public Member (String name, String email, int age, String address, Strubg phone) {
this(name, email, age, address, phone);
}
public Member (String name, String email, int age, String address, Strubg phone) {
this.name = name;
this.email = email;
this.age = age;
this.address = address;
this.phone = phone;
}
}
- 이 클래스의 인스턴스를 만들려면 원하는 매개변수를 모두 포함한 생성자 중 가장 짧은 것을 골라 호출하면 된다.
Member member1 = new Member("test", "test@email.com", "50", "한국", "01012341234);
- 위와 같은 생성자는 사용자가 설정하길 원하지 않는 매개변수까지 포함하기 쉬운데, 어쩔 수 없이 그런 매개변수에도 값을 지정해줘야 한다.
- 매개변수가 늘아날 수록 클라이언트 코드를 작성하거나 읽기 어렵다.
- 코드를 읽을 때 각 값의 의미가 무엇인지 헷갈릴 것이고, 매개변수가 몇 개 인지도 주의해서 세어 보아야 한다.
- 타입이 같은 매개변수가 연달아 늘어서 있으면 찾기 어려운 버그로 이어질 수 있다.
- 클라이언트가 실수로 매개변수의 순서를 바꿔 건네줘도 컴파일러는 알아채지 못하고, 결국 런타임에 엉뚱한 동작을 하게 된다.
2. 자바빈즈 패턴
- 매개변수가 없는 생성자로 객체를 만든 후, setter 메소드를 호출해 원하는 매개변수의 값을 설정하는 방식
public class Member {
// 매개변수들은 기본값으로 초기화된다.(기본값이 있을 경우)
private String name = "";
private String email = "";
private int age = 0;
private String address = "";
private String phone = "";
public Member {
// setter메소드들
public void setName(String name) {
this.name = name;
}
public void setEmail(String email) {
this.email = email;
}
public void setAge(String age) {
this.age = age;
}
public void setAddress(String address) {
this.address = address;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
}
Member member2 = new Member();
member2.setName("test");
member2.setEmail("test@email.com");
member2.setAge(50);
member2.setAddress("서울");
member2.setPhone("01020203030);
- 인스턴스를 만들기 쉽고, 읽기 쉬운 코드로 변경되었다.
- 하지만 자바 빈즈 패턴에서는 객체 하나를 만들려면 메소드 여러 개를 호출해야 하고, 객체가 완전히 생성되기 전까지 일관성이 무너진 상태가 된다.
- 자바빈즈 패턴에서는 클래스를 불변으로 만들 수 없다.
3. 빌더 패턴
이런 두 가지 패턴에서 문제가 발생하는데, 이를 해결한 것이 빌더 패턴이다.
public class Member {
private String name;
private String email;
private int age;
private String address;
private String phone;
public static class Builder {
private final String name;
private final String email;
private int age;
private String address;
private String phone;
public builder(String name, String email) {
this.name = name;
this.email = email;
}
public Builder age(int val) {
age = val;
return this;
}
... 반복 ...
}
private Member(Builder builder) {
name = builder.name;
... 반복 ...
phone = builder.phone;
}
}
- Member 클래스는 불변, 모든 매개변수의 기본값들을 한곳에 모아 뒀다.
- 빌더의 세터 메소드들은 빌더 자신을 반환하기 때문에 연쇄적으로 호출할 수 있다.
-> 이런 방식을 Fluent API 혹은 Methos Chaining이라고 한다.
Member member3 = new Member.Builder("test3", "test3@email.com")
.age(50)
.address("제주도")
.phone("01034344545").build();
- 이 클라이언트 코드는 쓰기 쉽고, 읽기 쉽다.
4. 정리
- 생성자나 정적 팩토리가 처리해야할 매개변수가 많다면 빌더 패턴을 선택하는게 낫다.
- 매개변수 중 다 수가 필수가 아니거나 같은 타입이면 더 쓰는게 맞다.
- 빌더는 점층적 생성자보다 클라이언트 코드를 읽고 쓰기가 쉽다.
- 빌더는 자바 빈즈보다 훨씬 안전하다.
- 참고
'개발 > Java&Kotlin' 카테고리의 다른 글
[Java] private 생성자로 인스턴스화 막기, 의존 객체 주입 사용하기 (2) | 2023.01.09 |
---|---|
[Java] private 생성자나 열거 타입으로 싱글턴 보증하기 (0) | 2023.01.07 |
[Java] 생성자 대신 정적 팩토리 메소드 사용하기 (1) | 2023.01.01 |
[Spring] 스프링 배치(Spring Batch) 가이드 따라가기 (7) (0) | 2022.12.23 |
[Spring] 스프링 배치(Spring Batch) 가이드 따라가기 (6) (0) | 2022.12.20 |