디자인 패턴의 활용

[디자인 패턴의 활용] 빌더 패턴이란?

미로910 2024. 9. 26. 09:48
💡
1. 빌더 패턴에 대한 개념 이해 하고 코드로 구현할 수 있다.

 

빌더 패턴이란?

빌더 패턴은 복잡한 객체를 단계적으로 생성할 수 있도록 도와주는 디자인 패턴입니다.

특히 많은 옵션이나 매개변수를 가진 객체를 만들 때 유용합니다. 일반적인 생성자는 매개변수가 많아지면 복잡해지기 때문에, 빌더 패턴은 각 단계에서 선택적인 매개변수를 추가할 수 있게 해줍니다. (ex: 햄버거, 서브웨이)

 

햄버거 예제와 빌더 패턴

햄버거를 주문할 때, 특정 업체에서는 다양한 재료 중에서 자신만의 햄버거를 만들 수 있습니다. 먼저 빵과 패티 같은 필수 재료를 선택하고, 그다음으로 치즈, 양상추, 토마토 같은 선택적인 재료를 추가합니다. 이 과정은 빌더 패턴과 매우 유사합니다. 

 

필수 요소와 선택 요소

  • 필수 요소: 햄버거를 만들기 위해선 반드시 있어야 하는 재료가 있습니다. 예를 들어, 빵과 패티는 꼭 필요한 요소입니다. 빌더 패턴에서는 객체를 만들기 위한 필수 요소를 생성자를 통해 전달합니다.
  • 선택 요소: 필수 요소 외에도 고객이 추가할 수 있는 여러 선택적인 재료가 있습니다. 치즈, 토마토, 양상추는 꼭 있어야 하는 건 아니지만, 원할 경우 추가할 수 있습니다. 빌더 패턴에서는 이런 선택적인 요소들을 메서드로 추가할 수 있습니다.

 

package builder;

// 햄버거 클래스 : 빌더 패턴을 사용해 단계적으로 객체를 생성
public class Burger {

    // 필수요소와 선택적 요소가 있을 수 있다.
    private String bread;
    private String patty;
    private boolean cheese;
    private boolean tomato;
    private boolean lettuce;
    
    // 외부에서 직접 생성하지 못하도록 - private 생성자 선언
    // 내부 정적 클래스에서 생성된 상태값들을 받아 멤버 변수를 초기화 한다.
    private Burger(BurgerBuilder builder){
        this.bread = builder.bread;
        this.patty = builder.patty;
        this.cheese = builder.cheese;
        this.tomato = builder.tomato;
        this.lettuce = builder.lettuce;
    }

    // 반드시 정적 내부 클래스를 선언한다.
    public static class BurgerBuilder {
        private String bread;
        private String patty;
        private boolean cheese = false;
        private boolean tomato = false;
        private boolean lettuce = false;
        
    // 필수 매개변수를 받을 생성자를 설계한다.
    public BurgerBuilder(String bread, String patty){
        this.bread = bread;
        this.patty = patty;
    }
    // 선택적 요소를 단계적으로 추가할 수 있도록 메서드르 설계해 준다.
    public BurgerBuilder addCheese(){
        this.cheese = true;
        return this; // 메서드 체이닝 지원
    }

    public BurgerBuilder addTomato(){
        this.tomato = true;
        return this; // 메서드 체이닝 지원
    }

    public BurgerBuilder addLettuce(){
        this.lettuce = true;
        return this; // 메서드 체이닝 지원
    }

// 핵심 1 - 최종적으로 Burger 객체를 반환하는 메서드를 생성(만들어 준다)
public Burger build(){
    return new Burger(this);
}

    } // end of inner class

    @Override
    public String toString() {
        return "Burger [bread=" + bread + ", patty=" + patty + ", cheese=" + cheese + ", tomato=" + tomato
                + ", lettuce=" + lettuce + "]";
    }


    
}

▶️ alt + shift + s (Override)

 

"빠른 초기화"라는 개념은 변수를 선언함과 동시에 값을 할당하여 초기화하는 것을 의미.

    private boolean cheese = false;
package builder;

public class BurgerStore {

    public static void main(String[] args) {
        Burger burger1 =  new Burger
        .BurgerBuilder("부드러운빵", "소고기")
        .addCheese()
        .addTomato()
        .build();

        System.out.println(burger1);
        System.out.println("-------------");

        Burger 치즈와양상추버거 = new Burger.BurgerBuilder("빵", "닭고기")
        .addLettuce()
        .addTomato()
        .build();

        System.out.println(치즈와양상추버거);

    }

}

실행 결과______

 

요약

즉 빌더 패턴은 복잡한 객체를 단계적으로 생성할 수 있도록 도와주는 디자인 패턴입니다.

 


✨this

this:
자기 자신을 가리키는 참조입니다. 클래스의 인스턴스 메서드 내에서 사용하면 현재 객체를 참조할 수 있습니다.

this():
클래스 내부에서 다른 생성자를 호출할 때 사용됩니다. 주로 생성자 오버로딩에서 코드를 재사용하기 위해 사용됩니다.

return this:
메서드가 자기 자신의 참조를 반환하는 경우입니다. 주로 메서드 체이닝 패턴에서 사용됩니다.