본문 바로가기
디자인 패턴

9. Builder Pattern

by spaul 2023. 12. 5.

▣ What is Builder Pattern?

A builder is a generative design pattern that allows you to create complex objects step by step.

 

빌더는 복잡한 객체들을 단계별로 생성할 수 있도록 하는 생성 디자인 패턴입니다. 클래스가 여러 개의 생성자 인자를 사용할 때, 빌더 패턴의 사용을 고려할 수 있습니다.

 

제품의 영양 정보를 나타내는 클래스를 만들어본다고 생각해보겠습니다. 영양 정보에는 1회당 제공량, 제품의 용량, 1회 제공량당 칼로리, 지방, 나트륨(소듐), 탄수화물 등의 영양정보를 제공합니다. 이 클래스의 생성자를 만들기 위해서 아래와 같이 만들어보겠습니다.

 

Java를 비롯한 대부분의 객체 지향성 언어들은 메소드 오버로딩을 지원하므로, 생성자 오버로딩을 통하여 아래와 같이 객체를 생성할 때 입력한 인자의 개수에 따라 다른 생성자를 선택하도록 할 수 있습니다. 하지만 일일이 생성자의 매개변수의 위치를 기억하고 있어야 되고 인자의 자료형이 비슷한 경우 런타임 오류가 발생할 수 있다는 것입니다.

(자바에는 파이썬의 keyword argument와 같은 general한 방법이 딱히 없는걸로 알고 있습니다)

 

위와 같은 문제를 해결하기 위해 빌더 패턴을 사용해보죠. 빌더 패턴은 아래와 같이 클래스 내부에 inner class를 만들고 그를 이용하여객체를 생성할 때 사용합니다.

public class NutritionFacts {
    private final int servingSize;
    private final int servings;
    private final int calories;
    private final int fat;
    private final int sodium;
    private final int carbohydrate;

    public static class Builder {
        // Required parameters
        private final int servingSize;
        private final int servings;
        // Optional parameters - initialized to default vals
        private int calories = 0;
        private int fat = 0;
        private int sodium = 0;
        private int carbohydrate = 0;

        public Builder(int servingSize, int servings) {
            this.servingSize = servingSize;
            this.servings = servings;
        }

        public Builder calories(int val) {
            calories = val;
            return this;
        }

        public Builder fat(int val) {
            fat = val;
            return this;
        }

        public Builder sodium(int val) {
            sodium = val;
            return this;
        }

        public Builder carbohydrate(int val) {
            carbohydrate = val;
            return this;
        }

        public NutritionFacts build() {
            return new NutritionFacts(this);
        }
    }

    private NutritionFacts(Builder builder) {
        servingSize = builder.servingSize;
        servings = builder.servings;
        calories = builder.calories;
        fat = builder.fat;
        sodium = builder.sodium;
        carbohydrate = builder.carbohydrate;
    }
}

 

NutritionFacts 클래스의 inner class인 Bulider는 static class이기 때문에 객체를 생성하지 않아도 사용할 수 있게 됩니다.  Builder의 메서드인 calories(), fat(), sodium() 등을 사용해 멤버변수들을 설정해주고, 마지막으로 build()를 통해 NutritionFacts() 클래스를 생성하고 반환합니다. 그러면 아래의 private으로 설정된 NutritionFacts의 생성자가 수행되면서 우리가 Builder를 통해 설정한 멤버 변수들의 값이 저장될 것입니다. 

 

그리고 메인함수에서 아래와 같이 사용하면 됩니다.

public class Main {
    public static void main(String[] args) {
        NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8)
                .calories(100)
                .sodium(35)
                .carbohydrate(27)
                .build();
    }
}

 

또한 이렇게 빌더 패턴을 사용하면 객체를 생성 후 객체의 상태가 절대 변경되지 않는 immutable한 클래스를 만들 수 있게 됩니다.

 

이렇게 간단하게 빌더 패턴에 대해서 알아보았습니다.

 

References

[1] 조용주, 고급객체지향프로그래밍

[2] Eric Freeman, Head Frist Design Patterns

'디자인 패턴' 카테고리의 다른 글

8. Factory Method Pattern, Abstract Factory Patter  (0) 2023.12.02
7. Decorator Pattern  (0) 2023.11.28
6. Iterator Pattern  (0) 2023.11.14
5. Singleton Pattern  (0) 2023.11.13
4. Observer Pattern  (0) 2023.11.07