Java에서 객체를 생성할 때, 생성자의 매개변수가 많거나 특정 필드만 선택적으로 초기화해야 하는 경우가 있습니다. 이런 상황에서는 빌더 패턴을 활용하면 코드의 가독성과 유지보수성을 높일 수 있습니다. 이번 글에서는 Lombok을 사용하지 않고 직접 빌더 패턴을 구현하는 방법을 알아보겠습니다.
1. 빌더 패턴이란?
빌더 패턴은 객체 생성 시점에 복잡한 생성자 호출을 피하고, 가독성과 유연성을 높이기 위해 사용하는 생성 패턴입니다. 이를 통해 객체 생성 코드가 명확해지고, 선택적 필드만 설정할 수 있는 장점이 있습니다.
2. 빌더 패턴의 필요성
- 매개변수 순서 문제 해결: 생성자에 많은 매개변수가 있을 때, 매개변수의 순서를 헷갈릴 위험이 있습니다.
- 가독성: 메서드 체이닝 방식으로 필드를 설정하기 때문에 코드를 읽고 이해하기 쉽습니다.
- 불변성: 빌더 패턴을 사용하면 객체 생성 후 변경할 수 없는 불변 객체를 쉽게 만들 수 있습니다.
3. Lombok 없이 빌더 패턴 구현하기
Lombok의 @Builder 애노테이션은 객체 생성 시 빌더 클래스를 자동으로 생성해주지만, Lombok을 사용하지 않고도 수동으로 빌더 패턴을 구현할 수 있습니다.
예제 코드: User 클래스
public class User {
// 필드 정의
private String firstName;
private String lastName;
private int age;
private String city;
// private 생성자: 빌더를 통해서만 객체 생성 가능
private User(Builder builder) {
this.firstName = builder.firstName;
this.lastName = builder.lastName;
this.age = builder.age;
this.city = builder.city;
}
// 정적 내부 클래스인 Builder 클래스
public static class Builder {
private String firstName;
private String lastName;
private int age;
private String city;
// 필드별 체이닝 메서드
public Builder firstName(String firstName) {
this.firstName = firstName;
return this;
}
public Builder lastName(String lastName) {
this.lastName = lastName;
return this;
}
public Builder age(int age) {
this.age = age;
return this;
}
public Builder city(String city) {
this.city = city;
return this;
}
// 빌더 메서드: User 객체 생성 및 반환
public User build() {
return new User(this);
}
}
@Override
public String toString() {
return "User{" +
"firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", age=" + age +
", city='" + city + '\'' +
'}';
}
}
4. 빌더 패턴 사용 예시
위에서 작성한 User 클래스를 사용하여 객체를 생성하는 방법은 다음과 같습니다:
public class Main {
public static void main(String[] args) {
User user = new User.Builder()
.firstName("John")
.lastName("Doe")
.age(30)
.city("New York")
.build();
System.out.println(user);
}
}
5. 빌더 패턴의 장점
- 가독성: 체이닝 방식을 통해 객체 생성 코드가 간결해집니다.
- 유연성: 필수 필드와 선택 필드를 구분하여 필요에 따라 특정 필드만 설정할 수 있습니다.
- 불변성: 객체가 생성된 후에는 상태를 변경할 수 없기 때문에 스레드 안전성과 안정성을 높일 수 있습니다.
6. setter와의 차이점
빌더 패턴과 setter는 객체의 필드 설정 방법에서 중요한 차이가 있습니다:
- 객체 생성 시점: 빌더 패턴은 객체를 생성할 때 필드를 설정하지만, setter는 이미 생성된 객체의 필드를 수정합니다.
- 불변성: 빌더 패턴은 불변 객체를 생성하는 데 유리하지만, setter는 객체의 상태를 변경할 수 있어 불변성을 유지할 수 없습니다.
- 캡슐화: setter는 외부에서 객체의 필드에 접근해 변경할 수 있기 때문에 캡슐화의 원칙을 위배할 수 있습니다.
7. 마무리
Lombok 없이 빌더 패턴을 구현하면 코드가 다소 길어질 수 있지만, 객체 생성의 가독성과 유연성이 크게 향상됩니다. 특히, 불변 객체가 필요하거나 선택적 필드가 많은 객체를 생성할 때는 빌더 패턴을 사용하는 것이 좋은 선택입니다. 앞으로 객체 생성이 복잡해질 때 직접 빌더 패턴을 구현하면 좋을 것같습니다.
'IT' 카테고리의 다른 글
상태 없는 객체와 static 메서드 활용법 (0) | 2024.11.13 |
---|---|
Light house 그리고 웹사이트 품질 테스트? (0) | 2024.11.12 |
Implements vs extends (4) | 2024.11.10 |
CI/CD란? (0) | 2024.11.09 |
Auto Boxing/Unboxing: 숨겨진 성능 문제 (0) | 2024.11.08 |