알아두면 쓸데있는 IT 잡학사전

개발/JAVA +16

1. 개요

뭔가가 만들어 지는 과정은 꽤나 복잡할 수가 있습니다. 게다가 그 복잡한 과정이 순서대로 실행되어야 할 때도 있습니다. 객체의 생성에 있어서 이런 복잡한 과정들을 분리해 내는 것이 Builder 패턴입니다. 


2. 예제

//---------------- 복잡한 과정을 거쳐서 만들어 지는 객체가 될 Hero 클래스 ---------------- 
package design.pattern.builder;

public class Hero {
    private String armSource;
    private String legSource;
    private String name;
    
    public Hero(String name) {
        super();
        this.name = name;
    }
    public void setArmSource(String armSource) {
        this.armSource = armSource;
    }
    public void setLegSource(String legSource) {
        this.legSource = legSource;
    }
    public void showResult(){
        System.out.println(armSource +"로 만든 팔과 " + legSource +"로 만든 다리를 가진 " + name);
    }
}
//---------------- 복잡한 Hero 객체를 만들어내기 위한 객체 생성과정을 관리하는 Builder 인터페이스 ---------------- 
package design.pattern.builder;

public interface Builder {
    void makeArm();
    void makeLeg();
    Hero getResult();
}
//---------------- 복잡한 Hero 객체를 실제로 만들어내는 Builder의 구현체인 배트맨 찍어내는 클래스 ------------------
package design.pattern.builder;

public class BatmanBuilder implements Builder {
    private Hero batman;
    BatmanBuilder(){
        batman = new Hero("배트맨");
    }
    public void makeArm() {
        batman.setArmSource("돈지랄");
    }
    public void makeLeg() {
        batman.setLegSource("돈지랄");
    }
    public Hero getResult() {
        return batman;
    }
}
//---------------- Builder를 관리해 주는 Director ---------------- 
package design.pattern.builder;

public class Director {
    private Builder builder;
    public Director(Builder builder) {
        this.builder = builder;
    }
    public void build(){
        builder.makeArm();
        builder.makeLeg();
    }
    public Hero getHero(){
        return builder.getResult();
    }
}
//---------------- Director를 이용해 Hero를 찍어내는 Test클래스 -------------
package design.pattern.builder;

public class Test {
    public static void main(String[] args) {
        Builder builder = new BatmanBuilder();
        Director director = new Director(builder);
        director.build();
        Hero hero = director.getHero();
        hero.showResult();
    }
}

---------------- 테스트 결과 -------------
돈지랄로 만든 팔과 돈지랄로 만든 다리를 가진 배트맨

Hero라는 클래스가 있습니다. 이 클래스는 그냥 생성자만 호출해서는 아무 쓸모없는 클래스입니다. 이런 저런 정보들이 많이 쎄팅이 되어야 비로소 쓸만한 객체가 됩니다.(예제에서는 setArmSource()과 setLegSource()와 같은 게 그런 복잡한 세팅 과정에 관여하는 메쏘듭니다.) 따라서 이 클래스의 객체를 생성하는 과정은 매우 번거롭습니다.

이런 번거로운 과정을 Director에서 간단하게 build()라는 메쏘드로 해결을 하려고 합니다. build()라는 메쏘드는 참 간단한 것 같은데, 번거로운 과정을 어떻게 다 커버하느냐는 결국 Builder에 위임해서 해결합니다.

Builder는 비교적 세부적인 사항들을 다룹니다. 이에 비해 Director는 좀 더 포괄적인 과정은 다룹니다. 위의 예제의 경우는 Builder는 팔은 어떻게 만들어 지고 다리는 어떻게 만들어지는 지 등과 같은 것을 다루며(세부적인 사항인 makeArm(), makeLeg()와 같은 메쏘드), Director는 팔을 만들고 다리를 만들면 대략 Hero 하나 완성시킬 수 있다는 전체적인 로직(포괄적인 과정인 build() 메쏘드)을 다룹니다. 즉, Director는 다른 Hero를 만드는데도 활용할 수 있지만, Builder는 각각의 Hero에 국한됩니다.

위의 예제는 예제인 만큼 간단하게 만들었습니다만, Hero를 만들기 위해서 수십수백 가지의 정보가 세팅되어야 한다고 칩시다. 이럴 때, Hero의 생성자에 그런 정보들을 다 세팅해줄 수는 없습니다.


3. UML을 벗어나서...

위에서는 등장인물이 Builder(interface)와 그 구현체들, 그를 관리하는 Director 그리고 만들어지는 생산품(Hero) 등이 있었습니다. 그러나, 이는 그냥 전형적이 UML 모냥새를 나타내는 것 뿐이고, Builder 패턴에 있어서는 저런 UML을 벗어나는 경우들이 허다합니다.

Builder에서의 포인트는 "뭔가 복잡한 과정을 거쳐 만들어지는 객체가 있는데, 이때 이 복잡한 과정을 Builder에게 담당시키겠다"는 것입니다. 따라서 Builder와 Product 두 개만으로도 구성될 수 있습니다. 즉, Builder 자체가 Abstract Class나 인터페이스가 아니라 그냥 클래스 일수도 있습니다.

StringBuilder와 같은 것이 대표적인 예입니다. StringBuilder는 이름 그대로 String을 만들어냅니다. 코드를 봅시다.

String ab = new StringBuilder("a").append("b").toString();

여기서 StringBuilder는 결국 "ab"라는 String을 만들기 위한 것입니다. StringBuilder 자체가 의미를 가지는 것이 아니라, 만들어 내는 String이 의미를 가지는 것입니다.

'개발 > JAVA' 카테고리의 다른 글

오라클, 자바 SE 전면 유료화…서브스크립션 모델 전환  (0) 2018.08.13
[Design Pattern]Mediator  (0) 2018.07.17
[Design Pattern]Flyweight  (0) 2018.07.16
[Design Pattern]Prototype  (0) 2018.07.16
[Design Pattern]Observer  (0) 2018.07.16