// ❌ 나쁜 예: 복잡한 생성자와 불명확한 객체 생성
public class Airplane {
public Airplane(float wingspan, String powerplant, String avionics,
int crewSeats, int passengerSeats, String type, String customer) {
// 매개변수가 너무 많고 순서를 기억하기 어려움
// 일부는 필수, 일부는 선택적일 수 있음
}
}
// 클라이언트 코드
Airplane cropDuster = new Airplane(9f, "single piston", null, 1, 1, "Crop Duster", "Joe");
Airplane glider = new Airplane(57.1f, null, null, 1, 0, "Glider", "Tim"); // null이 많아짐
문제점:
해결책:

public class AerospaceEngineer { // Director
private AirplaneBuilder builder;
public void constructAirplane() {
builder.createNewAirplane();
builder.buildWings(); // 1단계
builder.buildPowerplant(); // 2단계
builder.buildAvionics(); // 3단계
builder.buildSeats(); // 4단계
}
}
왜 필요한가?
public abstract class AirplaneBuilder {
protected Airplane airplane;
public abstract void buildWings();
public abstract void buildPowerplant();
public abstract void buildAvionics();
public abstract void buildSeats();
public Airplane getAirplane() { return airplane; }
}
왜 Abstract Class/Interface인가?
public class CropDuster extends AirplaneBuilder {
public void buildWings() {
airplane.setWingspan(9f); // 구체적인 구현
}
public void buildPowerplant() {
airplane.setPowerplant("single piston");
}
// ... 나머지 메서드 구현
}
공통 코드 재사용
public abstract class AirplaneBuilder {
protected Airplane airplane; // 모든 Builder가 공유하는 필드
// 공통 메서드 (모든 Builder가 같은 방식으로 사용)
public void createNewAirplane() {
airplane = new Airplane(customer, type);
}
public Airplane getAirplane() {
return airplane;
}
}
부분적 구현 강제
상속 계층 구조
protected Airplane airplane

Client
|
| 1. Concrete Builder 생성
| 2. Director에 Builder 전달
↓
Director (무엇을 만들지)
|
| build() 호출
↓
Builder (어떻게 만드는지의 규격)
↑
|
ConcreteBuilder1, ConcreteBuilder2, ...
(실제 구현 - 다양한 표현)
|
↓
Product (복잡한 객체)
핵심 흐름:
1. Client가 Concrete Builder 생성
2. Client가 Director를 생성하고 Builder를 주입
3. Client가 Director.build() 호출
4. Director가 Builder의 메서드를 순서대로 호출
5. Builder가 단계별로 Product 조립
6. Client가 Builder에서 완성된 Product 획득
// Product: 만들어질 복잡한 객체
public class Airplane {
private String type;
private float wingspan;
private String powerplant;
private int crewSeats;
private int passengerSeats;
private String avionics;
private String customer;
public Airplane(String customer, String type) {
this.customer = customer;
this.type = type;
}
// Setters
public void setWingspan(float w) { this.wingspan = w; }
public void setPowerplant(String p) { this.powerplant = p; }
public void setAvionics(String a) { this.avionics = a; }
public void setNumberSeats(int crew, int passenger) {
this.crewSeats = crew;
this.passengerSeats = passenger;
}
// Getters
public String getCustomer() { return customer; }
public String getType() { return type; }
}
// Builder: 추상 빌더
public abstract class AirplaneBuilder {
protected Airplane airplane;
protected String customer;
protected String type;
// 공통 메서드
public Airplane getAirplane() {
return airplane;
}
public void createNewAirplane() {
airplane = new Airplane(customer, type);
}
// 각 Concrete Builder가 구현해야 할 메서드
public abstract void buildWings();
public abstract void buildPowerplant();
public abstract void buildAvionics();
public abstract void buildSeats();
}
// Concrete Builder 1: 농업용 비행기
public class CropDuster extends AirplaneBuilder {
public CropDuster(String customer) {
super.customer = customer;
super.type = "Crop Duster v3.4";
}
public void buildWings() {
airplane.setWingspan(9f);
}
public void buildPowerplant() {
airplane.setPowerplant("single piston");
}
public void buildAvionics() {
// 농업용은 항공전자장비 불필요
}
public void buildSeats() {
airplane.setNumberSeats(1, 1);
}
}
// Concrete Builder 2: 전투기
public class FighterJet extends AirplaneBuilder {
public FighterJet(String customer) {
super.customer = customer;
super.type = "F-35 Lightning II";
}
public void buildWings() {
airplane.setWingspan(35.0f);
}
public void buildPowerplant() {
airplane.setPowerplant("dual thrust vectoring");
}
public void buildAvionics() {
airplane.setAvionics("military");
}
public void buildSeats() {
airplane.setNumberSeats(1, 0); // 조종사만
}
}
// Concrete Builder 3: 글라이더
public class Glider extends AirplaneBuilder {
public Glider(String customer) {
super.customer = customer;
super.type = "Glider v9.0";
}
public void buildWings() {
airplane.setWingspan(57.1f); // 긴 날개
}
public void buildPowerplant() {
// 글라이더는 엔진 없음
}
public void buildAvionics() {
// 기본 장비만
}
public void buildSeats() {
airplane.setNumberSeats(1, 0);
}
}
// Director: 생성 과정을 제어
public class AerospaceEngineer {
private AirplaneBuilder airplaneBuilder;
// Builder 설정
public void setAirplaneBuilder(AirplaneBuilder ab) {
airplaneBuilder = ab;
}
// 완성된 비행기 반환
public Airplane getAirplane() {
return airplaneBuilder.getAirplane();
}
// 비행기 생성 과정 (순서가 중요!)
public void constructAirplane() {
airplaneBuilder.createNewAirplane();
airplaneBuilder.buildWings(); // 1단계
airplaneBuilder.buildPowerplant(); // 2단계
airplaneBuilder.buildAvionics(); // 3단계
airplaneBuilder.buildSeats(); // 4단계
}
}
public class BuilderExample {
public static void main(String[] args) {
// 1. Director 생성 (엔지니어 고용)
AerospaceEngineer engineer = new AerospaceEngineer();
// 2. Concrete Builder들 생성 (주문 접수)
AirplaneBuilder cropDusterBuilder = new CropDuster("Farmer Joe");
AirplaneBuilder fighterJetBuilder = new FighterJet("The Navy");
AirplaneBuilder gliderBuilder = new Glider("Tim Rice");
// 3. 농업용 비행기 제작
engineer.setAirplaneBuilder(cropDusterBuilder);
engineer.constructAirplane();
Airplane cropDuster = engineer.getAirplane();
System.out.println(cropDuster.getType() +
" 완성 → 고객: " + cropDuster.getCustomer());
// 4. 전투기 제작 (같은 Director, 다른 Builder)
engineer.setAirplaneBuilder(fighterJetBuilder);
engineer.constructAirplane();
Airplane fighter = engineer.getAirplane();
System.out.println(fighter.getType() +
" 완성 → 고객: " + fighter.getCustomer());
// 5. 글라이더 제작
engineer.setAirplaneBuilder(gliderBuilder);
engineer.constructAirplane();
Airplane glider = engineer.getAirplane();
System.out.println(glider.getType() +
" 완성 → 고객: " + glider.getCustomer());
}
}
Crop Duster v3.4 완성 → 고객: Farmer Joe
F-35 Lightning II 완성 → 고객: The Navy
Glider v9.0 완성 → 고객: Tim Rice
// Product
public class Document {
private StringBuilder content = new StringBuilder();
public void addParagraph(String text) {
content.append(text);
}
public String getContent() {
return content.toString();
}
}
// Abstract Builder
public abstract class DocumentBuilder {
protected Document document = new Document();
public abstract void addHeader(String text);
public abstract void addParagraph(String text);
public abstract void addFooter(String text);
public Document getDocument() {
return document;
}
}
// Concrete Builder 1: HTML
public class HTMLBuilder extends DocumentBuilder {
public void addHeader(String text) {
document.addParagraph("<h1>" + text + "</h1>\n");
}
public void addParagraph(String text) {
document.addParagraph("<p>" + text + "</p>\n");
}
public void addFooter(String text) {
document.addParagraph("<footer>" + text + "</footer>\n");
}
}
// Concrete Builder 2: Markdown
public class MarkdownBuilder extends DocumentBuilder {
public void addHeader(String text) {
document.addParagraph("# " + text + "\n\n");
}
public void addParagraph(String text) {
document.addParagraph(text + "\n\n");
}
public void addFooter(String text) {
document.addParagraph("---\n" + text + "\n");
}
}
// Director
public class DocumentDirector {
private DocumentBuilder builder;
public void setBuilder(DocumentBuilder b) {
this.builder = b;
}
public void constructDocument() {
builder.addHeader("제목");
builder.addParagraph("본문 내용 1");
builder.addParagraph("본문 내용 2");
builder.addFooter("© 2024");
}
public Document getDocument() {
return builder.getDocument();
}
}
// 사용
DocumentDirector director = new DocumentDirector();
// HTML 문서 생성
director.setBuilder(new HTMLBuilder());
director.constructDocument();
Document htmlDoc = director.getDocument();
// Markdown 문서 생성 (같은 순서, 다른 형식)
director.setBuilder(new MarkdownBuilder());
director.constructDocument();
Document mdDoc = director.getDocument();
| 요소 | 역할 | 특징 |
|---|---|---|
| Director | 생성 순서 정의 (what) | Builder를 사용해 단계별 생성 과정 제어 |
| Builder (Abstract) | 생성 인터페이스 정의 | 각 부품을 만드는 메서드 시그니처 제공 |
| Concrete Builder | 실제 생성 구현 (how) | 구체적인 표현 방식으로 객체 조립 |
| Product | 최종 결과물 | 복잡한 구조를 가진 객체 |
| Builder | Abstract Factory |
|---|---|
| 단계별 객체 생성 | 즉시 완성된 객체 반환 |
| Director가 생성 과정 제어 | Client가 직접 Factory 메서드 호출 |
| 나중에 getProduct()로 결과 획득 | 메서드 호출 즉시 객체 반환 |
| 복잡한 객체의 조립 과정에 집중 | 관련된 객체 패밀리 생성에 집중 |
❌ 인터페이스가 불안정하면 사용하지 말 것
❌ 단순한 객체에는 과도한 설계