[디자인패턴] 빌더 패턴(Builder Pattern)

Damsul·2023년 1월 18일
0

디자인패턴

목록 보기
8/15
post-thumbnail

복잡한 객체를 생성하는 방법과 표현하는 방법을 정의하는 클래스를 별도로 분리하여, 서로 다른 표현이라도 이를 생성할 수 있는 동일한 절차를 제공하는 패턴

  1. 복잡한 객체의 생성방법과 표현방법을 분리해야할 때
  2. 생성방법과 구성방법 모두 캡슐화 해야할 때
    사용한다.

출처 : 위키디피아

  • Builder : 객체의 요소들을 생성하기 위한 추상 클래스
  • ConcreteBuilder : Builder가 정의한 메서드 구현
  • Director : Builder 인터페이스를 사용하는 객체를 합성
  • Product : 생성할 복합 객체를 표현

예제

카페음료를 만드는 과정을 구현한다고 가정해보자. 카페음료를 만들기 위해 필요한 재료들을 정해놓고(Builder), 바리스타가 해당 재료들을 섞어 카페음료를 만들어낼 수 있다(Director).

  • Product

[Coffee.java]

public class Coffee {
    private final String base;
    private final String liquid;
    private final String syrup;
    private final int price;


    public Coffee(String base, String liquid, String syrup, int price) {
        this.base = base;
        this.liquid = liquid;
        this.syrup = syrup;
        this.price = price;
    }

    @Override
    public String toString() {
        return "Coffee [" +
            "base='" + base + '\'' +
            ", liquid='" + liquid + '\'' +
            ", syrup='" + syrup + '\'' +
            ", price=" + price +
            ']';
    }
}
  • Builder

[CoffeeBuilder.java]

public interface CoffeeBuilder {
    CoffeeBuilder base(String base);
    CoffeeBuilder liquid(String liquid);
    CoffeeBuilder syrup(String syrup);
    CoffeeBuilder price(int price);
    Coffee build();
}
  • ConcreteBuilder

[DefaultCoffeeBuilder.java]

public class DefaultCoffeeBuilder implements CoffeeBuilder {
    private String base;
    private String liquid;
    private String syrup;
    private int price;

    @Override
    public CoffeeBuilder base(String base) {
        this.base = base;
        return this;
    }

    @Override
    public CoffeeBuilder liquid(String liquid) {
        this.liquid = liquid;
        return this;
    }

    @Override
    public CoffeeBuilder syrup(String syrup) {
        this.syrup = syrup;
        return this;
    }

    @Override
    public CoffeeBuilder price(int price) {
        this.price = price;
        return this;
    }

    @Override
    public Coffee build() {
        return new Coffee(base, liquid, syrup, price);
    }

}
  • Director

[CoffeeDirector.java]

public class CoffeeDirector {

    private final CoffeeBuilder coffeeBuilder;

    public CoffeeDirector(CoffeeBuilder coffeeBuilder) {
        this.coffeeBuilder = coffeeBuilder;
    }

    public Coffee americano() {
        return coffeeBuilder.base("espresso")
            .liquid("water")
            .price(2500)
            .build();
    }

    public Coffee vanillaLatte() {
        return coffeeBuilder.base("espresso")
            .liquid("milk")
            .syrup("vanillaSyrup")
            .price(4000)
            .build();
    }
}

[Client.java]

public class Client {
    public static void main(String[] args) {
        CoffeeDirector barista = new CoffeeDirector(new DefaultCoffeeBuilder());
        Coffee americano = barista.americano();
        System.out.println("아메리카노 " + americano.toString());

        Coffee vanillaLatte = barista.vanillaLatte();
        System.out.println("바닐라라떼 " + vanillaLatte.toString());

        CoffeeBuilder builder = new DefaultCoffeeBuilder();
        Coffee latte = builder.base("espresso")
                                .liquid("milk")
                                .price(3500)
                                .build();
        System.out.println("라뗴 : " + latte.toString());
    }
}
  • 실행 결과

장단점

  • 장점
    • 필요한 데이터만 설정할 수 있다.
    • 유연성을 확보할 수 있다.
    • 가독성을 높일 수 있다.
    • 변경 가능성을 최소화할 수 있다.
  • 단점
    • 복잡도가 증가할 수 있다.
      • 패턴이 여러 개의 새 클래스를 생성하기 때문

주의할 점

lombok의 @Builder는 GoF의 빌더 패턴과 같지 않음

  • lombok의 @Builder는 Director를 제공하지 않는다
profile
내 맘대로 작성하는 개발일지/ 작고 소중한 개발창고

0개의 댓글