August 21, 2021
๋ณธ ๊ฒ์๋ฌผ์ Java ์ธ์ด๋ก ๋ฐฐ์ฐ๋ ๋์์ธ ํจํด ์
๋ฌธ - Yuki Hiroshi ์ ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๊ณต๋ถํ ๊ฒ์ ์ ๋ฆฌํ๋ฉฐ Typescript๋ก ์ฌ์์ฑํด๋ณธ ๋ด์ฉ์
๋๋ค.
๋น๋ฉ์ ์ธ์ธ ๋ ์ฐ์ ์ง๋ฐ์ ๋ค์ง๊ณ , ๊ณจ๊ฒฉ์ ์ธ์ฐ๊ณ , ์๋์์ ์๋ก ์กฐ๊ธ์ฉ ๋ง๋ค์ด ๊ฐ๋ค.
์ด๋ ๊ฒ ์ผ๋ฐ์ ์ผ๋ก ๋ณต์กํ ๊ฑด๋ฌผ์ ์ธ์ธ ๋ ํ ๋ฒ์ ์์ฑ์ํค๊ธฐ๋ ์ด๋ ต๋ค.
์ด ์ฒ๋ผ ์ฐ์ ์ ์ฒด๋ฅผ ๊ตฌ์ฑํ๊ณ ์๋ ๊ฐ ๋ถ๋ถ์ ๋ง๋ค๊ณ ๋จ๊ณ๋ฅผ ๋ฐ์ ๋ง๋ค์ด ๊ฐ๋
๊ตฌ์กฐ๋ฅผ ๊ฐ์ง ์ธ์คํด์ค๋ฅผ ์์ ์ฌ๋ฆฌ๋ ๊ฒ์ด Builder ํจํด ์ด๋ค.
์์ฑํ ์์ ํ๋ก๊ทธ๋จ์ ๋ฌธ์๋ฅผ ์์ฑํ๋ ํ๋ก๊ทธ๋จ์ด๋ฉฐ,
๋ฌธ์๋ ํ์ดํ์ ํ ๊ฐ ํฌํจํ๋ค, ๋ฌธ์์ด์ ๋ช ๊ฐ ํฌํจํ๋ค, ๊ฐ๋ณ ํญ๋ชฉ์ ๋ช ๊ฐ ํฌํจํ๋ค๋ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
| ์ด๋ฆ | ํด์ค |
|---|---|
| Builder | ๋ฌธ์๋ฅผ ๊ตฌ์ฑํ๊ธฐ ์ํ ๋ฉ์๋๋ฅผ ๊ฒฐ์ ํ๋ ์ถ์ ํด๋์ค |
| Director | ํ ๊ฐ์ ๋ฌธ์๋ฅผ ๋ง๋๋ ํด๋์ค |
| TextBuilder | ์ผ๋ฐ ํ ์คํธ๋ฅผ ์ด์ฉํด์ ๋ฌธ์๋ฅผ ๋ง๋๋ ํด๋์ค |
| HTMLBuilder | HTML ํ์ผ์ ์ด์ฉํด์ ๋ฌธ์๋ฅผ ๋ง๋๋ ํด๋์ค |
| Main | ๋์ ํ ์คํธ์ฉ ํด๋์ค |
// 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();
}// Typescript
abstract class Builder {
public abstract makeTitle(title: String): void;
public abstract makeString(str: String): void;
public abstract makeItems(items: String[]): void;
public abstract close(): void;
}Builder ํด๋์ค๋ ๋ฌธ์๋ฅผ ๋ง๋ค ๋ฉ์๋๋ค์ ์ ์ธํ๊ณ ์๋ ์ถ์ ํด๋์ค์ด๋ค.
// Java
public class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public void construct() { // ๋ฌธ์ ๊ตฌ์ถ
builder.makeTitle("์๋
ํ์ธ์"); // ํ์ดํ
builder.makeString("์์นจ๊ณผ ๋ฎ์"); // ๋ฌธ์์ด
builder.makeItems(new String[]{"์ข์ ์์นจ์
๋๋ค", "์๋
ํ์ธ์"}); // ๊ฐ๋ณ ํญ๋ชฉ
builder.close(); // ๋ฌธ์ ์์ฑ
}
}// Typescript
class Director {
private builder: Builder;
public constructor(builder: Builder) {
this.builder = builder;
}
// ๋ฌธ์ ๊ตฌ์ถ
public construct = (): void => {
this.builder.makeTitle('์๋
ํ์ธ์'); // ํ์ดํ
this.builder.makeString('์์นจ๊ณผ ๋ฎ์'); // ๋ฌธ์์ด
this.builder.makeItems(['์ข์ ์์นจ์
๋๋ค', '์๋
ํ์ธ์']); // ๊ฐ๋ณ ํญ๋ชฉ
this.builder.close(); // ๋ฌธ์ ์์ฑ
};
}Director ํด๋์ค๋ Builder ํด๋์ค๋ก ์ ์ธ๋์ด ์๋ ๋ฉ์๋๋ฅผ ์ฌ์ฉํด์ ๋ฌธ์๋ฅผ ๋ง๋ญ๋๋ค.
Director ํด๋์ค์ ์์ฑ์์ ์ธ์๋ Builderํ์ธ๋ฐ,
์ค์ ๋ก Builder ํด๋์ค์ ์ธ์คํด์ค๊ฐ ์ธ์๋ก ์ฃผ์ด์ง๋ ๊ฒฝ์ฐ๋ ์๋ค.
Builder ํด๋์ค๋ ์ถ์ ํด๋์ค์ด๋ฉฐ, ์ด๋ ์ธ์คํด์ค๋ฅผ ๋ง๋ค ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
์ฆ, Director ํด๋์ค์ ์์ฑ์์ ์ ๋ฌ๋๋ ๊ฒ์ Builder ํด๋์ค์ ํ์ ํด๋์ค์ธ TextBuilder, HTMLBuilder ํด๋์ค์ ์ธ์คํด์ค์ด๋ค.
construct ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด ๋ฌธ์๊ฐ ๋ง๋ค์ด์ง๋ค.
// Java
public class TextBuilder extends Builder {
private StringBuffer buffer = new StringBuffer();
public void makeTitle(String title) { // ํ์ดํ
buffer.append("=================\n");
buffer.append("<" + title + ">\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");
}
}
public void close() { // ์ข
๋ฃ์
buffer.append("=================\n");
}
public String getResult() { // ์์ฑํ ๋ฌธ์
return buffer.toString();
}
}// Typescript
class TextBuilder extends Builder {
private buffer: string[] = [];
public makeTitle = (title: String): void => {
this.buffer.push('=================\n');
this.buffer.push(title + '\n');
};
public makeString = (str: String): void => {
this.buffer.push(str + '\n');
};
public makeItems = (items: String[]): void => {
for (let i = 0; i < items.length; i++) {
this.buffer.push(items[i] + '\n');
}
};
public close = (): void => {
this.buffer.push('=================\n');
};
public getResult = (): String => {
return this.buffer.join('');
};
}TextBuilder ํด๋์ค๋ Builder ํด๋์ค์ ํ์ ํด๋์ค์ด๋ค.
์ผ๋ฐ ํ ์คํธ๋ฅผ ์ฌ์ฉํด์ ๋ฌธ์๋ฅผ ๊ตฌ์ถํ๊ณ ๊ฒฐ๊ณผ๋ฅผ String์ผ๋ก ๋ฐํํ๋ค.
// Java
import java.io.*;
public class HTMLBuilder extends Builder {
private String filename;
private PrintWriter writer;
public void makeTitle(String title) {
filename = title + ".html";
// ์ค๋ต
}
public void makeString(String str) {
writer.println("<p>" + str + "</p>");
}
public void makeItems(String[] items) {
for (int i = 0; i < items.length; i++) {
// ์ค๋ต
}
}
public void close() {
writer.close();
}
public String getResult() { // ํ์ผ๋ช
์ ๋ฐํ
return filename;
}
}HTML ํ์ผ์ ๋ง๋ค๊ณ ์์ฑํ๋ ๋ด์ฉ์ด๋ผ TS๋ ์๋ตํ๊ฒ ์ต๋๋ค.
HTMLBuilder ํด๋์ค๋ Builder ํด๋์ค์ ํ์ ํด๋์ค์ด๋ฉฐ, HTML ํ์ผ๋ก ๋ฌธ์๋ฅผ ๊ตฌ์ถํ๊ณ ํ์ผ๋ช ์ ๋ฐํํ๋ค.
public class Main {
public static void Main(String[] args) {
if (args.length != 1) {
usage();
System.exit(0);
}
if (args[0].equals("plain")) {
TextBuilder textbuilder = new TextBuilder();
Director director = new Director(textbuilder);
director.consturct();
String result = textbuilder.getResult();
System.out.println(result);
} else if (args[0].equals("html")) {
HTMLBuilder htmlbuilder = new HTMLBuilder();
Director director = new Director(htmlbuilder);
director.construct();
String filename = htmlbuilder.getResult();
System.out.println(filename + "๊ฐ ์์ฑ๋์์ต๋๋ค");
} else {
usage();
System.exit(0);
}
}
public static void usage() {
System.out.println("Usage: java Main plane ์ผ๋ฐ ํ
์คํธ๋ก ๋ฌธ์์์ฑ");
System.out.println("Usage: java Main html HTML ํ์ผ๋ก ๋ฌธ์์์ฑ");
}
}TextBuilder ํด๋์ค์ ์ธ์คํด์ค ํน์ HTMLBuilder ํด๋์ค์ ์ธ์คํด์ค๋ฅผ Director ํด๋์ค์ ์์ฑ์์๊ฒ ์ ๋ฌํ๋ค.
TexBuilder, HTMLBuilder๋ Builder ํด๋์ค์ ํ์ ํด๋์ค์ด๊ณ
Director๋ Builder์ ๋ฉ์๋๋ง์ ์ฌ์ฉํด์ ๋ฌธ์๋ฅผ ์์ฑํ๋ค.
Builder์ ๋ฉ์๋๋ง์ ์ฌ์ฉํ๋ค๋ ๊ฒ์ Director๋ ์ค์ ๋ก ๋์ํ๋ ๊ฒ์ด TextBuilder์ธ์ง, HTMLBuilder์ธ์ง ๋ชจ๋ฅธ๋ค๋ ๋ป์ด๋ค.
๋ฐ๋ผ์ Builder๋ ๋ฌธ์๋ฅผ ๊ตฌ์ถํ๋ ค๋ ๋ชฉ์ ์ ๋ฌ์ฑํ๊ธฐ ์ํด์ ํ์ ์ถฉ๋ถํ ๋ฉ์๋๊ตฐ์ ์ ์ธํ ํ์๊ฐ ์๋ค.
๋จ, ์ผ๋ฐ ํ ์คํธ๋ HTML ํ์ผ์ ๊ณ ์ ์ ๋ฉ์๋๊น์ง Builder๊ฐ ์ ๊ณตํด์๋ ์๋๋ค.
Builder
Builder ์ญํ ์ ์ธ์คํด์ค๋ฅผ ์์ฑํ๊ธฐ ์ํ ์ธํฐํ์ด์ค๋ฅผ ๊ฒฐ์ ํ๋ค.
์ธ์คํด์ค์ ๊ฐ ๋ถ๋ถ์ ๋ง๋ค๊ธฐ ์ํ ๋ฉ์๋๊ฐ ์ค๋น๋์ด ์์ผ๋ฉฐ, ์์ ํ๋ก๊ทธ๋จ์์๋ Builder ํด๋์ค๊ฐ ์ด ์ญํ ์ ๋ด๋นํ๋ค.
ConcreteBuilder
ConcreteBuilder ์ญํ ์ Builder ์ญํ ์ ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๊ณ ์๋ ํด๋์ค์ด๋ค.
์ค์ ์ธ์คํด์ค ์์ฑ์ผ๋ก ํธ์ถ๋๋ ๋ฉ์๋, ์ต์ข ๊ฒฐ๊ณผ๋ฅผ ์ป๊ธฐ ์ํ ๋ฉ์๋๊ฐ ์ค๋น๋์ด ์๋ค.
์์ ํ๋ก๊ทธ๋จ์์๋ TextBuilder, HTMLBuilder ํฌ๋์ค๊ฐ ์ด ์ญํ ์ ๋ด๋นํ๋ค.
Director
Director ์ญํ ์ Builder ์ญํ ์ ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํด์ ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ค.
ConcreteBuilder ์ญํ ๊ณผ ๊ด๊ณ์์ด ์ ๋๋ก ๊ธฐ๋ฅํ๋๋ก Builder ์ญํ ์ ๋ฉ์๋๋ง์ ์ฌ์ฉํ๋ค.
์์ ํ๋ก๊ทธ๋จ์์๋ Director ํด๋์ค๊ฐ ์ด ์ญํ ์ ๋ด๋นํ๋ค.
Client
Builder ํจํด์ ์ด์ฉํ๋ ์ญํ ์ด๋ฉฐ, ์์ ํ๋ก๊ทธ๋จ์์๋ Main ํด๋์ค๊ฐ ์ญํ ์ ๋ด๋นํ์๋ค.
GoF ์ฑ ์์๋ Client ์ญํ ์ Builder ํจํด ์์ ํฌํจ๋์ด ์์ง ์๋ค.
![]()
OOP์์ โ๋๊ฐ ๋ฌด์์ ์๊ณ ์์๊น?โ, โ์ด๋ค ํด๋์ค๊ฐ ์ด๋ค ๋ฉ์๋๋ฅผ ์ฌ์ฉํ ์ ์์๊น?โ ๋ ์๋นํ ์ค์ํ์ฌ ์ฃผ์ํ๋ฉฐ ํ๋ก๊ทธ๋๋ฐ์ ํ ํ์๊ฐ ์๋ค.
๋ชจ๋ฅด๊ธฐ ๋๋ฌธ์ ๊ตํ์ด ๊ฐ๋ฅํ๊ณ , ๊ต์ฒด๊ฐ ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ ๋ถํ์ผ๋ก์ ๊ฐ์น๊ฐ ๋๋ค.
๊ตํ๊ฐ๋ฅ์ฑ์ ํด๋์ค์ ์ค๊ณ์๋ก์จ ํญ์ ๊ธฐ์ตํ ํ์๊ฐ ์๋ค.
Builder ํด๋์ค๋ ๋ฌธ์๋ฅผ ๊ตฌ์ถํ ๋ ํ์ ์ถฉ๋ถํ ๋ฉ์๋๊ตฐ์ ์ ์ธํด์ผ ํ๋ค.
์๋ํ๋ฉด Director ํด๋์ค์ ์ฃผ์ด์ง ๋๊ตฌ๋ Builder ํด๋์ค๊ฐ ์ ๊ณตํ๋ ๋๊ตฌ์ด๊ธฐ ๋๋ฌธ์ด๋ค.
์์ ํ๋ก๊ทธ๋จ์์๋ Text์ HTML ํ์์ ํ์ผ๋ง์ Build ํ์ง๋ง, ๋ฏธ๋์ ASDF๋ผ๋ ํ์์ด ๋์์ ๋ ASDFBuilder ํด๋์ค๋ฅผ ๋ง๋ค ์ ์์ ์ง, ์๋ก์ด ๋ฉ์๋๊ฐ ํ์ํ ์ง๋ ๋ชจ๋ฅธ๋ค.
์ด์ฒ๋ผ ๋ชจ๋ ๊ฒ์ ์์ํ ์๋ ์๊ธฐ ๋๋ฌธ์, ๊ฐ๊น์ด ๋ฏธ๋์ ๋ฐ์ํ ๊ฒ์ผ๋ก ์์๋๋ ๋ณํ์ ์ ์ํ ์ ์๋๋ก ์ค๊ณํด์ผ ํ๋ค.
Template Method
Director ์ญํ ์ด Builder ์ญํ ์ ์ ์ด, Template Method ํจํด์์๋ ์์ ํด๋์ค๊ฐ ํ์ ํด๋์ค๋ฅผ ์ ์ดํ๋ค.
Composite
Builder ํจํด์ ์ํด ๋ง๋ค์ด์ง ์์ฑ๋ฌผ์ Composite ํจํด์ด ๋๋ ๊ฒฝ์ฐ๊ฐ ์๋ค.
Abstract Factory
Builder ํจํด๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ณต์กํ ์ธ์คํด์ค๋ฅผ ์์ ํ๋ค.
Facade
Director ์ญํ ์ Builder ์ญํ ์ ๋ณต์กํ ๋ฉ์๋๋ฅผ ์กฐํฉํด์ ์ธ์คํด์ค๋ฅผ ๊ตฌ์ถํ๋ ์ธํฐํ์ด์ค๋ฅผ ์ธ๋ถ์ ์ ๊ณตํ๋ ๊ฒ (construct)์ด๋ค. Facade ํจํด์ Facade ์ญํ ์ ๋ด๋ถ ๋ชจ๋์ ์กฐํฉํด ๋จ์ํ ์ธํฐํ์ด์ค๋ฅผ ์ธ๋ถ์ ์ ๊ณตํ๋ค.