반응형

의도

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

 

활용성

  • 복합 객체의 생성 알고리즘이 이를 합성하려는 요소 객체들이 무엇인지 이들의 조립방법에 독립적일 때
  • 합성할 객체들의 표현이 서로 다르더라도 생성 절차에서 이를 지원해야 할 때

 

결과

  • 제품에 대한 내부 표현을 다양하게 변화할 수 있다.
  • 생성과 표현에 필요한 코드를 분리한다.
  • 복합 객체를 생성하는 절차를 좀 더 세밀하게 나눌 수 있다.

 

협력 방법

  • 사용자는 Director 객체를 생성하고, 이렇게 생성한 객체를 자신이 원하는 Builder 객체로 합성해 나간다.
  • 제품의 일부가 구축(built)될 때마다 Director는 Builder에 통보한다.
  • Builder는 Director의 요청을 처리하여 제품에 부품을 추가한다.
  • 사용자는 Builder에서 제품을 검색한다.

 

구조

실제 구현 구조

소스코드

//Director
public class ToyMaker {
    private final ToyBuilder toyBuilder;

    public ToyMaker(ToyBuilder toyBuilder) {
        this.toyBuilder = toyBuilder;
    }

    public Toy getToy() {
        return this.toyBuilder.getToy();
    }

    public void constructToy(){
        this.toyBuilder.buildType();
        this.toyBuilder.buildHair();
        this.toyBuilder.buildDress();
        this.toyBuilder.buildShoes();
    }
}
//Builder
public abstract class ToyBuilder {
    public abstract void buildType();
    public abstract void buildHair();
    public abstract void buildDress();
    public abstract void buildShoes();
    public abstract Toy getToy();
}
//ConcreateBuilder
public class BallToyBuilder extends ToyBuilder {
    private final Toy toy;

    public BallToyBuilder(){
        toy = new Toy();
    }

    @Override
    public void buildType() {
        toy.setType("Ball");
    }

    @Override
    public void buildHair() {}

    @Override
    public void buildDress() {}

    @Override
    public void buildShoes() {}

    @Override
    public Toy getToy() {
        return this.toy;
    }
}
//ConcreateBuilder
public class HumanToyBuilder extends ToyBuilder {
    private final Toy toy;

    public HumanToyBuilder() {
        this.toy = new Toy();
    }

    @Override
    public void buildType() {
        toy.setType("Human");
    }

    @Override
    public void buildHair() {
        toy.setHair("yello hair");
    }

    @Override
    public void buildDress() {
        toy.setDress("black dress");
    }

    @Override
    public void buildShoes() {
        toy.setShoes("sneakers");
    }

    @Override
    public Toy getToy() {
        return this.toy;
    }
}
//Product
public class Toy {
    private String type = "";
    private String hair = "";
    private String dress = "";
    private String shoes = "";

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getHair() {
        return hair;
    }

    public void setHair(String hair) {
        this.hair = hair;
    }

    public String getDress() {
        return dress;
    }

    public void setDress(String dress) {
        this.dress = dress;
    }

    public String getShoes() {
        return shoes;
    }

    public void setShoes(String shoes) {
        this.shoes = shoes;
    }

    @Override
    public String toString() {
        return this.hashCode() + " " +
                this.type + "Toy{" +
                "hair='" + hair + '\'' +
                ", dress='" + dress + '\'' +
                ", shoes='" + shoes + '\'' +
                '}';
    }
}
public class Main {
    public static void main(String[] args) {
        //공 장난감
        ToyMaker ballToyMaker = new ToyMaker(new BallToyBuilder());
        Toy ballToy = ballToyMaker.getToy();
        System.out.println(ballToy);
        ballToyMaker.constructToy();
        System.out.println(ballToy);
        System.out.println("------------------------------------------");
        //인간형 장난감
        ToyMaker humanToyMaker = new ToyMaker(new HumanToyBuilder());
        Toy humanToy = humanToyMaker.getToy();
        System.out.println(humanToy);
        humanToyMaker.constructToy();
        System.out.println(humanToy);
    }
}

 

관련 패턴

  • 복잡한 객체를 생성해야 할 때, 추상 팩토리 패턴은 빌더 패턴과 비슷한 모습을 보인다.
  • 차이점은 빌더 패턴은 복잡한 객체의 단계별 생성에 중점을 둔 반면, 추상 팩토리 패턴은 제품의 유사군들이 존재할 때 유연한 설계에 중점을 둔다.
  • 빌더 패턴은 생성의 마지막 단계에서 생성한 제품을 반환하는 반면, 추상 팩토리 패턴에서는 만드는 즉시 제품을 반환한다.
    • 추상 팩토리 패턴에서 만드는 제품은 꼭 모여야만 의미있는 것이 아니라 하나만으로도 의미가 있기 때문이다.

 

GOF에 등장하는 빌더 패턴과 이펙티브 자바의 빌더 패턴은 보는 관점이 다르다.

 


[참고자료]

리처드 헬름, 랄프 존슨, 존 블리시디스, 『GoF의 디자인 패턴 : 재사용성을 지닌 객체지향 소프트웨어의 핵심요소』, 김정아 번역, 프로텍미디어(2015)

https://www.geeksforgeeks.org/builder-design-pattern/

https://commons.wikimedia.org/wiki/File:Patron_builder.PNG?uselang=ko#filehistory

 

 

반응형

+ Recent posts