Design Pattern | Builder Pattern (빌더 패턴)

Builder 패턴이란?

  • Build라는 단어는 구조를 가진 큰 것을 빌드하는 의미이다.
  • 복잡한 구조를 가진 것을 만들 때 단번에 완성하기가 어렵다. 우선 전체를 구축하고 있는 각 부분을 만들어, 단계를 밟아 조립해 가게 된다.
  • 동일한 구축 공정, 다른 표현 객체을 생성한다.
  • 생성자에 들어갈 매개 변수가 많든 적든 차례차례 매개 변수를 받아들이고 모든 매개 변수를 받은 뒤에 이 변수들을 통합해서 한번에 사용을 한다.
  • Builder 패턴은 구조를 가진 인스턴스를 구축하는 방법이다.
  • GoF 디자인 패턴에서는 생성과 관련된 디자인 패턴 으로 분류된다.

Builder 패턴 예제 프로그램

문서를 일반 텍스트 및 HTML 형식으로 출력하는 예제 프로그램이다.

Class Diagram
Builder Pattern Class Diagram

1. Builder 클래스

문서를 구성하기 위한 메소드를 정의한 추상 클래스이다.

Builder.java

public abstract class Builder {
    public abstract void makeTitle(String title);
    public abstract void makeString(String str);
    public abstract void makeItems(String[] items);
    public abstract void close();
}

2. Guide 클래스

하나의 문서를 만드는 클래스이다.

Guide.java

package com.devkuma.designpattern.creational.builder;

public class Guide {

    private Builder builder;

    public Guide(Builder builder) {
        this.builder = builder;
    }

    public void construct() {
        builder.makeTitle("야유회에 대해서");
        builder.makeString("일시");
        builder.makeItems(new String[]{
                "2022/3/14 (월)",
                "11:00~",
        });
        builder.makeString("장소");
        builder.makeItems(new String[]{
                "xxx 캠핌장",
        });
        builder.makeString("준비물");
        builder.makeItems(new String[]{
                "회비",
                "고기",
                "음료수",
        });
        builder.close();
    }
}

3. TextBuilder 클래스

일반 텍스트로 문서를 만드는 클래스이다.

TextBuilder.java

package com.devkuma.designpattern.creational.builder;

public class TextBuilder extends Builder {

    private StringBuffer buffer = new StringBuffer();

    public void makeTitle(String title) {
        buffer.append("==============================\n");
        buffer.append("'" + title + "'\n");
        buffer.append("\n");
    }

    public void makeString(String str) {
        buffer.append("- " + str + "\n");
    }

    public void makeItems(String[] items) {
        for (int i = 0; i < items.length; i++) {
            buffer.append(" - " + items[i] + "\n");
        }
        buffer.append("\n");
    }

    public void close() {
        buffer.append("==============================\n");
    }

    public String getResult() {
        return buffer.toString();
    }
}

3. HTMLBuilder 클래스

HTML 파일로 문서를 작성하는 클래스이다.

HTMLBuilder.java

package com.devkuma.designpattern.creational.builder;

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

public class HtmlBuilder extends Builder {

    private String filename;
    private PrintWriter writer;

    public void makeTitle(String title) {
        filename = title + ".html";
        try {
            writer = new PrintWriter(new FileWriter(filename));
        } catch (IOException e) {
            e.printStackTrace();
        }
        writer.println("<html><head><title>" + title + "</title></head><body>");
        writer.println("<h1>" + title + "</h1>");
    }

    public void makeString(String str) {
        writer.println("<p>" + str + "</p>");
    }

    public void makeItems(String[] items) {
        writer.println("<ul>");
        for (int i = 0; i < items.length; i++) {
            writer.println("<li>" + items[i] + "</li>");
        }
        writer.println("</ul>");
    }

    public void close() {
        writer.println("</body></html>");
        writer.close();
    }

    public String getResult() {
        return filename;
    }
}

5. Main 클래스

예제 프로그램을 실행하는 메인 클래스이다.

Main.java

package com.devkuma.designpattern.creational.builder;

public class Main {
    public static void main(String[] args) {

        if (args.length != 1) {
            System.exit(0);
        }
        if (args[0].equals("plain")) {
            TextBuilder textbuilder = new TextBuilder();
            Guide guide = new Guide(textbuilder);
            guide.construct();
            String result = textbuilder.getResult();
            System.out.println(result);
        } else if (args[0].equals("html")) {
            HtmlBuilder htmlbuilder = new HtmlBuilder();
            Guide guide = new Guide(htmlbuilder);
            guide.construct();
            String filename = htmlbuilder.getResult();
            System.out.println(filename + "이 작성되었습니다.");
        } else {
            System.exit(0);
        }
    }
}

6. 실행 결과

텍스트

==============================
'야유회에 대해서'

- 일시
 - 2022/3/14 (월)
 - 11:00~

- 장소
 - xxx 캠핌장

- 준비물
 - 회비
 - 고기
 - 음료수

==============================

HTML

<html><head><title>야유회에 대해서</title></head><body>
<h1>야유회에 대해서</h1>
<p>일시</p>
<ul>
<li>2022/3/14 (월)</li>
<li>11:00~</li>
</ul>
<p>장소</p>
<ul>
<li>xxx 캠핌장</li>
</ul>
<p>준비물</p>
<ul>
<li>회비</li>
<li>고기</li>
<li>음료수</li>
</ul>
</body></html>

7. Builder 패턴의 장점

예제 프로그램을 보면, Main 클래스는 문서의 구축 방법(Builder 클래스의 메소드)을 모른다. Main 클래스는 Guide 클래스의 construct 메소드를 호출하는 것만으로 문장을 구축할 수 있다.
그리고, Guide 클래스는 Builder 클래스를 사용해 문서를 작성을 하지만, Guide 클래스는 자신이 실제로 이용하고 있는 클래스가 무엇인가(TextBuilder인가 HtmlBuilder인가)를 모른다.
TextBuilder의 인스턴스를 Guide에 주어도 HTMLBuilder의 인스턴스를 Guide에 주어도 올바르게 기능하는 것은 Guide 클래스가 Builder 클래스의 구체적인 클래스를 모르기 때문이다.
모르기 때문에 교체가 가능한 교체가 가능하기 때문에 부품으로서의 가치가 높아진다.