소개
서브웨이에 방문하면 손님은 빵 크기, 빵 종류, 추가토핑, 야채, 소스를 선택해야 하나의 샌드위치가 완성됩니다. 이와 같이 하나의 객체를 만드는 과정에서 옵션이 다양할 때 사용하는 패턴이 빌더 패턴 (Builder Pattern) 입니다. 이 포스팅에서 빌더 패턴을 설명하지는 않고, 빌더 패턴을 적용한 서브웨이 샌드위치를 생성하는 소스코드를 공유합니다.
소스코드는 타입스크립트를 기반으로 작성하였습니다.
열거체
const enum EBreadSize {
SMALL = 1,
LARGE = 2,
}
const enum EBreadType {
WHITE = 1,
WHEAT = 2,
HONEY_OAT = 3,
HEARTY_ITALIAN = 4,
PARMESAN_OREGANO = 5,
FLAT_BREAD = 6,
}
const enum ETopping {
MEAT = 1,
CHEESE = 2,
AVOCADO = 3,
PEPPERONI = 4,
EGG_MAYO = 5,
BACON = 6,
OMELET = 7,
}
const enum EVegetable {
LETTUCE = 1,
TOMATO = 2,
ONION = 3,
OLIVE = 4,
JALAPENO = 5,
PIMENTO = 6,
CUCUMBER = 7,
PICKLE = 8,
AVOCADO = 9,
}
const enum ESauce {
RANCH = 1,
MAYONNAISE = 2,
SWEET_ONION = 3,
HONEY_MUSTARD = 4,
SWEET_CHILI = 5,
HOT_CHILI = 6,
SOUTHWEST_CHIPOTLE = 7,
MUSTARD = 8,
HORSERADISH = 9,
OLIVE_OIL = 10,
RED_WINE_VINEGAR = 11,
SALT = 12,
PEPPER = 13,
SMOKE_BBQ = 14,
ITALIAN_DRESSING = 15,
}
열거체 값에 대한 영문표기
const breadSizeEnglishMap = new Map<EBreadSize, string>([
[EBreadSize.SMALL, 'small'],
[EBreadSize.LARGE, 'large'],
])
const breadTypeEnglishMap = new Map<EBreadType, string>([
[EBreadType.WHITE, 'white'],
[EBreadType.WHEAT, 'wheat'],
[EBreadType.HONEY_OAT, 'honey oat'],
[EBreadType.HEARTY_ITALIAN, 'hearty italian'],
[EBreadType.PARMESAN_OREGANO, 'parmesan oregano'],
[EBreadType.FLAT_BREAD, 'flat bread'],
])
const toppingEnglishMap = new Map<ETopping, string>([
[ETopping.MEAT, 'meat'],
[ETopping.CHEESE, 'cheese'],
[ETopping.AVOCADO, 'avocado'],
[ETopping.PEPPERONI, 'pepperoni'],
[ETopping.EGG_MAYO, 'egg mayo'],
[ETopping.BACON, 'bacon'],
[ETopping.OMELET, 'omelet'],
])
const vegetableEnglishMap = new Map<EVegetable, string>([
[EVegetable.LETTUCE, 'lettuce'],
[EVegetable.TOMATO, 'tomato'],
[EVegetable.ONION, 'onion'],
[EVegetable.OLIVE, 'olive'],
[EVegetable.JALAPENO, 'jalapeno'],
[EVegetable.PIMENTO, 'pimento'],
[EVegetable.CUCUMBER, 'cucumber'],
[EVegetable.PICKLE, 'pickle'],
[EVegetable.AVOCADO, 'avocado'],
])
const sauceEnglishMap = new Map<ESauce, string>([
[ESauce.RANCH, 'ranch'],
[ESauce.MAYONNAISE, 'mayonnaise'],
[ESauce.SWEET_ONION, 'sweet onion'],
[ESauce.HONEY_MUSTARD, 'honey mustard'],
[ESauce.SWEET_CHILI, 'sweet chili'],
[ESauce.HOT_CHILI, 'hot chili'],
[ESauce.SOUTHWEST_CHIPOTLE, 'southwest chipotle'],
[ESauce.MUSTARD, 'mustard'],
[ESauce.HORSERADISH, 'horseradish'],
[ESauce.OLIVE_OIL, 'olive oil'],
[ESauce.RED_WINE_VINEGAR, 'red wine vinegar'],
[ESauce.SALT, 'salt'],
[ESauce.PEPPER, 'pepper'],
[ESauce.SMOKE_BBQ, 'smoke bbq'],
[ESauce.ITALIAN_DRESSING, 'italian dressing'],
])
빌더 인터페이스
interface IBuilder {
reset(): void
setBreadSize(breadSize: EBreadSize): IBuilder
setBreadType(breadType: EBreadType): IBuilder
setToppings(toppings: ETopping[]): IBuilder
setVegetables(vegetables: EVegetable[]): IBuilder
setSauces(sauces: ESauce[]): IBuilder
}
샌드위치 빌더 클래스
class SandwichBuilder implements IBuilder {
private breadSize: EBreadSize
private breadType: EBreadType
private toppings: ETopping[]
private vegetables: EVegetable[]
private sauces: ESauce[]
constructor() {
this.reset()
}
public reset(): void {
this.breadSize = EBreadSize.SMALL
this.breadType = EBreadType.WHEAT
this.toppings = []
this.vegetables = []
this.sauces = []
}
public setBreadSize(breadSize: EBreadSize): IBuilder {
this.breadSize = breadSize
return this
}
public setBreadType(breadType: EBreadType): IBuilder {
this.breadType = breadType
return this
}
public setToppings(toppings: ETopping[]): IBuilder {
this.toppings = toppings
return this
}
public setVegetables(vegetables: EVegetable[]): IBuilder {
this.vegetables = vegetables
return this
}
public setSauces(sauces: ESauce[]): IBuilder {
this.sauces = sauces
return this
}
public getResult(): string {
return `${breadSizeEnglishMap.get(this.breadSize)} ${breadTypeEnglishMap.get(this.breadType)} ${this.toppings
.map(topping => toppingEnglishMap.get(topping))
.join('+')} ${this.vegetables.map(vegetable => vegetableEnglishMap.get(vegetable)).join('+')} ${this.sauces
.map(sauce => sauceEnglishMap.get(sauce))
.join('+')}`
}
}
레시피를 알고 있는 디렉터 클래스
class Director {
public buildSandwich1(builder: IBuilder): void {
builder
.setBreadSize(EBreadSize.SMALL)
.setBreadType(EBreadType.WHEAT)
.setToppings([ETopping.MEAT, ETopping.CHEESE])
.setVegetables([EVegetable.ONION, EVegetable.TOMATO])
.setSauces([ESauce.RANCH])
}
public buildSandwich2(builder: IBuilder): void {
builder
.setBreadSize(EBreadSize.LARGE)
.setBreadType(EBreadType.PARMESAN_OREGANO)
.setToppings([ETopping.EGG_MAYO, ETopping.PEPPERONI, ETopping.MEAT])
.setVegetables([EVegetable.LETTUCE, EVegetable.TOMATO, EVegetable.AVOCADO, EVegetable.CUCUMBER])
.setSauces([ESauce.HORSERADISH, ESauce.SWEET_ONION, ESauce.MAYONNAISE])
}
}
사용 예시
const director = new Director()
const builder = new SandwichBuilder()
director.buildSandwich1(builder)
console.log(builder.getResult())
builder.reset()
director.buildSandwich2(builder)
console.log(builder.getResult())
결과
small wheat meat+cheese onion+tomato ranch
large parmesan oregano egg mayo+pepperoni+meat lettuce+tomato+avocado+cucumber horseradish+sweet onion+mayonnaise
'컴퓨터 공학 > Algorithm' 카테고리의 다른 글
프로그래머스 가장 큰 수 구하기 (0) | 2021.06.07 |
---|---|
백준 알고리즘 21738 얼음깨기 펭귄 C++ 코드 (0) | 2021.06.07 |
알고스팟 - 수강철회 (WITHDRAWAL) (0) | 2018.09.12 |
2-SAT (2-Satisfiability) (0) | 2018.09.12 |
알고스팟 - 변화하는 중간값 (RUNNINGMEDIAN) 설명 (0) | 2018.09.12 |