- Builder 패턴 : 복잡한 인스턴스를 조립한다
Builder 패턴은 구조를 가진 인스턴스를 만들어 가는 패턴으로, 뼈대를 만들고 아래에서 위로 만들어 간다.
- 어떤 경우에 사용할까?
Builder 패턴은 구체적인 하위 클래스를 모른다는 게 큰 장점이다. 모르기 때문에 교체가 가능하고, 교체되기 때문에 부품으로서의 가치가 높다. 클래스 설계자는 '교체 가능성'을 항상 염두에 둘 필요가 있다.
- 예제 코드
이름 | 설명 |
Builder | 문서를 구성하기 위한 메서드를 규정한 추상 클래스 |
Director | 하나의 문서를 만드는 클래스 |
TextBuilder | 텍스트(일반 문자열)를 이용하여 문서를 만드는 클래스 |
HTMLBuilder | HTML 파일을 이용하여 문서를 만드는 클래스 |
Main | 동작 테스트용 클래스 |
- Builder 클래스
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();
}
- Director 클래스
public class Director {
private Builder builder;
// 생성자
public Director(Builder builder) {
this.builder = builder;
}
// 문서를 만드는 메소드
public void construct() {
builder.makeTitle("Greeting");
builder.makeString("일반적인 인사");
builder.makeItems(new String[] {
"How are you?",
"Hello.",
"Hi."
});
builder.makeString("시간대별 인사");
builder.makeItems(new String[] {
"Good morning.",
"Good afternoon.",
"Good evening."
});
builder.close();
}
}
- TextBuilder 클래스
public class TextBuilder extends Builder {
private StringBuilder sb = new StringBuilder();
@Override
public void makeTitle(String title) {
sb.append("==============================\n");
sb.append("[");
sb.append(title);
sb.append("]\n\n");
}
@Override
public void makeString(String str) {
sb.append("■");
sb.append(str);
sb.append("\n\n");
}
@Override
public void makeItems(String[] items) {
for(String s : items) {
sb.append(" ·");
sb.append(s);
sb.append("\n");
}
sb.append("\n");
}
@Override
public void close() {
sb.append("==============================\n");
}
public String getTextResult() {
return sb.toString();
}
}
- HTMLBuilder 클래스
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class HTMLBuilder extends Builder {
private String filename = "untitled.html";
private StringBuilder sb = new StringBuilder();
@Override
public void makeTitle(String title) {
filename = title + ".html";
sb.append("<!DOCTYPE html>\n");
sb.append("<html>\n");
sb.append("<head><title>");
sb.append(title);
sb.append("</head></title>\n");
sb.append("<body>\n");
sb.append("<h1>");
sb.append(title);
sb.append("</h1>\n\n");
}
@Override
public void makeString(String str) {
sb.append("<p>");
sb.append(str);
sb.append("</p>\n\n");
}
@Override
public void makeItems(String[] items) {
sb.append("<ul>\n");
for(String s : items) {
sb.append("<li>");
sb.append(s);
sb.append("</li>\n");
}
sb.append("</ul>\n\n");
}
@Override
public void close() {
sb.append("</body>");
sb.append("</html>\n");
try {
Writer writer = new FileWriter(filename);
writer.write(sb.toString());
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public String getHTMLResult() {
return filename;
}
}
- Main 클래스
public class Main {
public static void main(String[] args) {
if(args.length != 1) {
usage();
System.exit(0);
}
if(args[0].equals("text")) {
TextBuilder textbuilder = new TextBuilder();
Director director = new Director(textbuilder);
director.construct();
String result = textbuilder.getTextResult();
System.out.println(result);
} else if(args[0].equals("html")) {
HTMLBuilder htmlbuilder = new HTMLBuilder();
Director director = new Director(htmlbuilder);
director.construct();
String filename = htmlbuilder.getHTMLResult();
System.out.println("HTML파일 : " + filename + "이 작성되었습니다.");
} else {
usage();
System.exit(0);
}
}
// 사용 방법을 표시한다
public static void usage() {
System.out.println("Usage: java Main text \t 텍스트로 문서 작성");
System.out.println("Usage: java Main html \t HTML 파일로 문서 작성");
}
}
참고문헌 : 유키 히로시 저/김성훈 역(2022), JAVA 언어로 배우는 디자인 패턴 입문, 영진닷컴
참고자료 : https://refactoring.guru/ko/design-patterns/builder