Menu
Coddy logo textTech

빌더 패턴

Coddy Java 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 87개 중 67번째.

빌더 패턴(Builder Pattern)은 많은 선택적 매개변수를 가진 복잡한 객체를 생성할 때 발생하는 일반적인 문제를 해결하는 생성 디자인 패턴입니다. 여러 개의 생성자를 만들거나 사용하지 않는 매개변수에 null을 전달하는 대신, 빌더를 사용하면 객체를 단계별로 생성할 수 있습니다.

필수 필드(name, email)와 선택적 필드(age, phone, address)를 가진 User 객체를 생성한다고 가정해 봅시다. 빌더가 없다면, 점층적 생성자(telescoping constructors)를 사용하거나 매개변수가 많은 복잡한 생성자가 필요할 것입니다. 빌더 패턴은 더 깔끔한 접근 방식을 제공합니다:

public class User {
    private final String name;    // 필수
    private final String email;   // 필수
    private final int age;        // 선택 사항
    private final String phone;   // 선택 사항
    
    private User(UserBuilder builder) {
        this.name = builder.name;
        this.email = builder.email;
        this.age = builder.age;
        this.phone = builder.phone;
    }
    
    public static class UserBuilder {
        private final String name;
        private final String email;
        private int age;
        private String phone;
        
        public UserBuilder(String name, String email) {
            this.name = name;
            this.email = email;
        }
        
        public UserBuilder age(int age) {
            this.age = age;
            return this;
        }
        
        public UserBuilder phone(String phone) {
            this.phone = phone;
            return this;
        }
        
        public User build() {
            return new User(this);
        }
    }
}

Builder의 메서드는 this를 반환하여, 객체를 생성하는 유연하고 가독성 좋은 방식인 메서드 체이닝(method chaining)을 가능하게 합니다:

User user = new User.UserBuilder("Alice", "alice@email.com")
    .age(25)
    .phone("555-1234")
    .build();

User 생성자가 private으로 설정되어 있음에 주목하세요. 객체는 오직 Builder를 통해서만 생성될 수 있습니다. 이 패턴은 객체에 선택적 필드가 많을 때 빛을 발하며, 긴 매개변수 목록보다 코드를 더 읽기 쉽고 오류가 적게 만들어 줍니다.

challenge icon

챌린지

쉬움

빌더 패턴(Builder Pattern)을 사용하여 피자 주문 시스템을 만들어 봅시다! 모든 가능한 토핑과 옵션에 대해 수십 개의 매개변수를 받는 생성자를 다루는 대신, 피자 커스터마이징을 깔끔하고 읽기 쉽게 만드는 유연한 빌더를 만들 것입니다.

코드는 두 개의 파일로 구성됩니다:

  • Pizza.java: 생성을 위해 빌더 패턴을 사용하는 Pizza 클래스를 만듭니다. 피자는 다음 필드를 가져야 합니다:

    size (String) - 필수, 피자 크기를 나타냄

    cheese (boolean) - 선택 사항, 기본값은 false

    pepperoni (boolean) - 선택 사항, 기본값은 false

    mushrooms (boolean) - 선택 사항, 기본값은 false

    Pizza 생성자는 private이어야 하며 PizzaBuilder만을 매개변수로 받아 빌더의 모든 값을 피자의 필드로 복사해야 합니다.

    getDescription() 메서드를 포함하세요. 이 메서드는 [size] Pizza with: [toppings] 형식의 문자열을 반환합니다. 여기서 toppings는 true인 토핑들(Cheese, Pepperoni, Mushrooms)을 쉼표로 구분한 목록입니다. 선택된 토핑이 없으면 토핑 부분은 no toppings라고 표시되어야 합니다.

    다음이 포함된 정적 내부 클래스 PizzaBuilder를 만듭니다:

    • 필수 size 매개변수를 받는 생성자
    • 각각 해당 boolean을 true로 설정하고 체이닝을 위해 this를 반환하는 cheese(), pepperoni(), mushrooms() 메서드
    • 새로운 Pizza를 반환하는 build() 메서드
  • Main.java: 피자 빌더가 작동하는 모습을 보여주세요! 피자 크기(String)와 치즈, 페퍼로니, 버섯을 각각 추가할지 여부를 나타내는 세 개의 yes/no 값(Strings)까지 총 네 개의 입력을 받게 됩니다.

    주어진 크기로 PizzaBuilder를 생성합니다. 그런 다음 각 yes/no 입력에 따라 적절한 토핑 메서드를 체이닝합니다. 입력이 "yes"이면 해당 토핑 메서드를 호출하고, "no"이면 건너뜁니다. 마지막으로 build()를 호출하여 피자를 생성합니다.

    완성된 피자에 대해 getDescription()을 호출한 결과를 출력합니다.

size (String), add cheese (String: "yes" or "no"), add pepperoni (String: "yes" or "no"), add mushrooms (String: "yes" or "no") 순서대로 네 개의 입력을 받게 됩니다.

예를 들어, 입력이 Large, yes, no, yes인 경우 출력은 다음과 같습니다: Large Pizza with: Cheese, Mushrooms

빌더 패턴을 사용하면 각 가능성에 대해 별도의 생성자를 만들 필요 없이 어떤 토핑 조합으로도 피자를 구성할 수 있다는 점에 주목하세요!

치트 시트

빌더 패턴(Builder Pattern)은 많은 선택적 매개변수를 가진 복잡한 객체를 생성하기 위한 생성 디자인 패턴입니다. 이 패턴은 객체를 단계별로 구축함으로써 생성자 체이닝(telescoping constructors)과 긴 매개변수 목록을 피할 수 있게 해줍니다.

구조

이 패턴은 다음과 같이 구성됩니다:

  • 빌더만 인자로 받는 private 생성자를 가진 클래스
  • 객체를 생성하는 정적 내부 빌더 클래스(static inner Builder class)
  • 메서드 체이닝(method chaining)을 위해 this를 반환하는 빌더 메서드들
  • 최종 객체를 생성하는 build() 메서드

구현 예시

public class User {
    private final String name;    // 필수
    private final String email;   // 필수
    private final int age;        // 선택
    private final String phone;   // 선택
    
    private User(UserBuilder builder) {
        this.name = builder.name;
        this.email = builder.email;
        this.age = builder.age;
        this.phone = builder.phone;
    }
    
    public static class UserBuilder {
        private final String name;
        private final String email;
        private int age;
        private String phone;
        
        public UserBuilder(String name, String email) {
            this.name = name;
            this.email = email;
        }
        
        public UserBuilder age(int age) {
            this.age = age;
            return this;
        }
        
        public UserBuilder phone(String phone) {
            this.phone = phone;
            return this;
        }
        
        public User build() {
            return new User(this);
        }
    }
}

메서드 체이닝을 사용한 활용

User user = new User.UserBuilder("Alice", "alice@email.com")
    .age(25)
    .phone("555-1234")
    .build();

빌더 패턴은 객체에 선택적 필드가 많을 때 이상적이며, 수많은 매개변수를 가진 생성자에 비해 가독성이 높고 유지보수가 쉬운 코드를 제공합니다.

직접 해보기

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // 입력 읽기
        String size = scanner.nextLine();
        String addCheese = scanner.nextLine();
        String addPepperoni = scanner.nextLine();
        String addMushrooms = scanner.nextLine();
        
        // TODO: 주어진 size로 PizzaBuilder 생성하기
        // TODO: yes/no 입력에 따라 토핑 메서드 체이닝하기
        // TODO: 피자를 빌드하고 설명을 출력하기
        
    }
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨