728x90
생성 - 빌더 패턴
빌더 패턴
- 동일한 인터페이스를 이용하여 여러 종류의 제품을 생성할 수 있다.
- 복잡한 물체를 동일 인터페이스를 이용하여 단계적으로 구현할 수도 있다.
빌더 패턴이 필요한 이유
상황
- 여러 종류의 제품을 만들 수 있어야 하는 경우
1. 상속을 이용
- 방법 : 기본 클래스를 확장하여 구현체별 서브 클래스를 생성한다.
- 문제점 : 구현체별 너무 많은 하위 클래스가 생성된다.
2. 가능한 경우에 대한 매개변수 생성
- 방법 : 모든 가능한 경우에 대해 생성자에 매개변수를 추가한다.
- 문제점 : 대부분의 경우 대부분의 매개변수가 사용되지 않는다.
3. 빌더 패턴 사용하는 경우
- 방법 : 객체 구성 코드를 빌더라는 개별 객체로 옮긴다.
- 장점 : 필요한 단계만 선택하여 객체를 생성할 수 있다.
구조
- 빌더 : 제품 생성의 공통 단계를 인터페이스로 정의한다.
- 구체 빌더 : 빌더 인터페이스를 따라 각 종류의 제품의 특성에 맞게 메서드를 구현한다.
- 빌더 인터페이스 외에 제품 특성별 새로운 메서드들이 추가될 수 있다.
- 제품 : 구체 빌더가 생성하는 제품
- 디렉터 : 빌더를 이용해 레시피대로 객체를 생성한다.
예시 : 서브웨이
- 빌더 패턴을 이용해 객체를 생성하는 방법에는 2가지가 있다.
- 디렉터를 이용해 정해진 레시피대로 객체를 생성한다. (서브웨이 썹픽)
- 커스텀 주문 : 직접 빌더의 메서드를 호출하여 객체를 생성한다. (하나하나 직접 지정)
public class Sandwich {
private String bread;
private String meat;
private String cheese;
private boolean isToasted;
private List<String> vegetables = new ArrayList<>();
private List<String> sauces = new ArrayList<>();
public void setBread(String bread) { this.bread = bread; }
public void setMeat(String meat) { this.meat = meat; }
public void setCheese(String cheese) { this.cheese = cheese; }
public void setToasted(boolean toasted) { isToasted = toasted; }
public void addVegetable(String vegetable) { this.vegetables.add(vegetable); }
public void addSauce(String sauce) { this.sauces.add(sauce); }
}
// 빌더 인터페이스
public interface SandwichBuilder {
void reset();
void chooseBread(String bread);
void addMeat(String meat);
void addCheese(String cheese);
void setToasted(boolean toasted);
void addVegetable(String vegetable);
void addSauce(String sauce);
Sandwich getResult();
}
// 구체 빌더
public class SubwaySandwichBuilder implements SandwichBuilder {
private Sandwich sandwich;
public SubwaySandwichBuilder() {
reset();
}
@Override
public void reset() {
sandwich = new Sandwich();
}
@Override
public void chooseBread(String bread) {
sandwich.setBread(bread);
}
@Override
public void addMeat(String meat) {
sandwich.setMeat(meat);
}
@Override
public void addCheese(String cheese) {
sandwich.setCheese(cheese);
}
@Override
public void setToasted(boolean toasted) {
sandwich.setToasted(toasted);
}
@Override
public void addVegetable(String vegetable) {
sandwich.addVegetable(vegetable);
}
@Override
public void addSauce(String sauce) {
sandwich.addSauce(sauce);
}
@Override
public Sandwich getResult() {
Sandwich result = this.sandwich;
reset();
return result;
}
}
// 디렉터
public class SubwayEmployee {
private SandwichBuilder builder;
public void setBuilder(SandwichBuilder builder) {
this.builder = builder;
}
// BMT 샌드위치 만들기
public void constructBMT() {
builder.reset();
builder.chooseBread("허니오트");
builder.addMeat("BMT");
builder.addCheese("모짜렐라");
builder.setToasted(true);
builder.addVegetable("양상추");
builder.addVegetable("토마토");
builder.addVegetable("오이");
builder.addSauce("랜치");
builder.addSauce("스위트어니언");
}
}
// 클라이언트
public class SubwayStore {
public static void main(String[] args) {
SubwayEmployee employee = new SubwayEmployee();
SubwaySandwichBuilder builder = new SubwaySandwichBuilder();
employee.setBuilder(builder);
// BMT 주문 (썹픽)
employee.constructBMT();
Sandwich bmt = builder.getResult();
System.out.println(bmt);
// 커스텀도 가능
builder.reset();
builder.chooseBread("플랫브레드");
builder.addMeat("로스트치킨");
builder.addCheese("슈레드치즈");
builder.setToasted(true);
builder.addVegetable("양상추");
builder.addSauce("스위트칠리");
Sandwich custom = builder.getResult();
System.out.println(custom);
}
}
적용점
- 많은 개수의 옵션 매개변수가 존재할 때
- 빌더 패턴을 이용하여 매개변수를 선택할 수 있게 되면, 수십개의 생성자가 필요 없게 된다.
class Pizza {
Pizza(int size) { ... }
Pizza(int size, boolean cheese) { ... }
Pizza(int size, boolean cheese, boolean pepperoni) { ... }
// ...
- 다양한 제품이 존재할 때
- 상속 대신 빌더 패턴을 이용하여 복잡한 계층 구조 없이 다양한 객체를 생성할 수 있다.
Reference
https://refactoring.guru/design-patterns/builder
Builder
Say you have a constructor with ten optional parameters. Calling such a beast is very inconvenient; therefore, you overload the constructor and create several shorter versions with fewer parameters. These constructors still refer to the main one, passing s
refactoring.guru
728x90
'설계 > 디자인 패턴' 카테고리의 다른 글
[디자인패턴] 생성 패턴 : 추상 팩토리 패턴 (0) | 2025.02.13 |
---|---|
[디자인패턴] 생성 패턴 : 팩토리 메서드 패턴 (1) | 2025.02.12 |
[디자인 패턴] 디자인 패턴이란? (0) | 2025.02.11 |