Notice
Recent Posts
Recent Comments
Link
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

개발자되기 프로젝트

인스턴스 생성 패턴 - Builder Pattern 본문

Java/디자인 패턴

인스턴스 생성 패턴 - Builder Pattern

Seung__ 2021. 11. 6. 00:43

1. GoF 디자인 패턴에서의 Builder Pattern이란?


  • 메서드의 조합으로 결과물을 생성하는 방법
  • 생성에 대한 과정과 각 결과물을 표현하는 방법을 분리하여 동일한 생성 과정에
    서로 다른 여러 결과물이 나올 수 있도록 함.
  • 클라이언트 코드는 Bulder가 제공하는 메서드를 기반으로 원하는 결과물을 얻을 수 있음
  • 단계별 생성에 중점을 두는 패턴
  • 새로운 결과물이 필요한 경우에도 동일한 과정으로 생성을 할 수 있음.

 

 

2. 의도와 동기


생성 과정과 구현 방법을 분리하여 동일한 생성에서 여러 다른 표현이 나올 수 있음.

 

 

 

3. Class Diagram(GoF)


  • Builder는 BuilPart1, BuilPart2, BuilPart3 메서드들이 진행되어야 하나의 결과물이 나올 수 있다.
  • Director는 builder를 포함함.

 

 

4. 객체 협력 (collaborations)


  • Builder Product의 각 요소들을 생성하는데 필요한 추상 메서드가 선언된 클래스나 인터페이스
  • ConcreteBuilder Builder에 선언된 메서드를 구현한 클래스
  • Director Builder 인터페이스를 사용하여 Product를 생성
  • Product 결과물

 

5. 중요한 결론 (consequence)


  • 생성과정과 구현을 분리함
  • 제품의 다양한 구현이 가능
  • 제품의 생산 과정을 더 세분화 할 수 있음
  • 클라이언트는 구체적인 사항을 알 필요가 없음
  • 생성자에 비슷한 변수가 많을 경우 유용함.

 

 

6. 예제


일련의 과정들이 추상화되고 같은 공정을 통해서 결과가 나온다.

 

public interface MakeReport {

	public void MakeHeader();
	public void MakeBody();
	public void MakeFooter();
	
	public String getReport();
}

위 인터페이스를 구현하여 TextReport, HTMLReport 등을 생성할 수 있음

 

 

 

 

7. Effective Java에서 사용하는 Builder Pattern


  • 생성자를 대체하는 방법
  • 객체를 생성할 때 매개 변수가 여러개인 경우 각각의 매개 변수가 점점 늘어가는 여러 개의 생성자를 사용하기 보다
    인스턴스 생성을 위한 Builder를 제공하여, 오류를 방지하고 이후 매개 변수가 늘어나더라도
    유연하게 수정할 수 있는 구조를 제공
  • 스프링에서 사용하고 있음.

 

 

8. 예제


public enum Topping {

    HAM, MUSHROOM, ONION, PEPPER, SAUSAGE;

}
public enum Size {

    SMALL, MEDIUM, LARGE
}
  • Pizza의 공통적인 속성
    • toppings를 가지고 있음.
    • Builder를 통해 Pizza 생성. -> 추상 클래스
    • Builder는 전반적인 생성과정을 나타냄.
    • self()  -> Builder 반환.
    • Pizza생성 시 Builder에 있는 toppings를 복사해옴.
public class Pizza {

    final Set<Topping> toppings;

    abstract static class Builder{

        //nonOf empty EnuSet반환.
        EnumSet<Topping> toppings = EnumSet.noneOf(Topping.class);

        public Builder addTopping(Topping topping){
            toppings.add(Objects.requireNonNull(topping));
            return self();
        }

        public Builder sauceInside(){
            return self();
        }

        abstract Pizza build();
        protected abstract Builder self();
    }

    Pizza(Builder builder){
        toppings = builder.toppings.clone();
    }

    public String toString(){
        return toppings.toString();
    }
}
  • Pizza를 상속받는 NyPizza
    • Pizza속성에 Size 추가
    • Builder는 Pizza.Builder를 상속받음 -> NyPizza에 맞는 생성과정을 구체화함.
public class NyPizza extends Pizza{

    private final Size size;


    public static class Builder extends Pizza.Builder{

        private final Size size;

        public Builder(Size size){
            this.size = Objects.requireNonNull(size);
        }

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

        @Override
        protected Builder self() {
            return this;
        }

    }

    //생성자 못쓰게 막음.
    private NyPizza(Builder builder) {
        super(builder);
        size = builder.size;
    }
}
  • Pizza를 상속받는 CalzonePizsza
    • Pizza속성에 sauceInside 추가
    • Builder는 Pizza.Builder를 상속받음 -> CalzonePizsza에 맞는 생성과정을 구체화함.
public class CalzonePizza extends Pizza{

    private final boolean sauceInside;

    public static class Builder extends Pizza.Builder{
        private boolean sauceInside = false;

        public Builder sauceInside(){
            sauceInside = true;
            return this;
        }

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

        @Override
        protected Builder self() {
            return this;
        }
    }

    private CalzonePizza(Builder builder) {
        super(builder);
        this.sauceInside = builder.sauceInside;
    }

    public String toString() {
        return toppings.toString() + " sauceInside: " + sauceInside;
    }

}
  • 사용하기
    • Builder를 통해 구체적인 Pizza를 생성.
    • 다양하게 구현이 가능.
public class Test {

    public static void main(String[] args) {

        Pizza nyPizza = new NyPizza.Builder(Size.LARGE).addTopping(Topping.HAM).addTopping(Topping.SAUSAGE).build();

        Pizza calzone = new CalzonePizza.Builder().addTopping(Topping.SAUSAGE).sauceInside().build();

        System.out.println(nyPizza);
        System.out.println(calzone);

    }
}

 

 

9. GitHub : 211105 Builder Pattern


 

GitHub - bsh6463/designPattern

Contribute to bsh6463/designPattern development by creating an account on GitHub.

github.com

 

Comments