Go로 작성된 빌더
빌더는 복잡한 객체들을 단계별로 생성할 수 있도록 하는 생성 디자인 패턴입니다.
다른 생성 패턴과 달리 빌더 패턴은 제품들에 공통 인터페이스를 요구하지 않습니다. 이를 통해 같은 생성공정을 사용하여 다양한 제품을 생산할 수 있습니다.
개념적인 예시
<0>빌더</0> 패턴은 필요한 제품이 복잡하고 이를 생성하기 위하여 여러 단계가 필요할 때 사용됩니다. 여러 생성 메서드들이 하나의 거대한 생성자보다 간단할 것입니다. 그러나 이러한 다단계 생성 프로세스의 잠재적인 문제는 완성되지 않은 불안정한 제품이 클라이언트에 노출될 수 있다는 점입니다. 빌더 패턴은 제품이 완성될 때까지 해당 제품을 비공개로 유지합니다.
아래 코드에는 다양한 유형의 주택들(igloo and normalHouse)이 다음 빌더들(iglooBuilder과 normalBuilder)에 의해 생성되는 것을 볼 수 있습니다. 각 주택 유형은 생성 단계들이 같습니다. 또 선택사항인 디렉터 구조체는 생성 프로세스를 정리하는 데 도움이 됩니다.
iBuilder.go: 빌더 인터페이스
package main type IBuilder interface { setWindowType() setDoorType() setNumFloor() getHouse() House } func getBuilder(builderType string) IBuilder { if builderType == "normal" { return newNormalBuilder() } if builderType == "igloo" { return newIglooBuilder() } return nil } normalBuilder.go: 구상 빌더
package main type NormalBuilder struct { windowType string doorType string floor int } func newNormalBuilder() *NormalBuilder { return &NormalBuilder{} } func (b *NormalBuilder) setWindowType() { b.windowType = "Wooden Window" } func (b *NormalBuilder) setDoorType() { b.doorType = "Wooden Door" } func (b *NormalBuilder) setNumFloor() { b.floor = 2 } func (b *NormalBuilder) getHouse() House { return House{ doorType: b.doorType, windowType: b.windowType, floor: b.floor, } } iglooBuilder.go: 구상 빌더
package main type IglooBuilder struct { windowType string doorType string floor int } func newIglooBuilder() *IglooBuilder { return &IglooBuilder{} } func (b *IglooBuilder) setWindowType() { b.windowType = "Snow Window" } func (b *IglooBuilder) setDoorType() { b.doorType = "Snow Door" } func (b *IglooBuilder) setNumFloor() { b.floor = 1 } func (b *IglooBuilder) getHouse() House { return House{ doorType: b.doorType, windowType: b.windowType, floor: b.floor, } } house.go: 제품
package main type House struct { windowType string doorType string floor int } director.go: 디렉터
package main type Director struct { builder IBuilder } func newDirector(b IBuilder) *Director { return &Director{ builder: b, } } func (d *Director) setBuilder(b IBuilder) { d.builder = b } func (d *Director) buildHouse() House { d.builder.setDoorType() d.builder.setWindowType() d.builder.setNumFloor() return d.builder.getHouse() } main.go: 클라이언트 코드
package main import "fmt" func main() { normalBuilder := getBuilder("normal") iglooBuilder := getBuilder("igloo") director := newDirector(normalBuilder) normalHouse := director.buildHouse() fmt.Printf("Normal House Door Type: %s\n", normalHouse.doorType) fmt.Printf("Normal House Window Type: %s\n", normalHouse.windowType) fmt.Printf("Normal House Num Floor: %d\n", normalHouse.floor) director.setBuilder(iglooBuilder) iglooHouse := director.buildHouse() fmt.Printf("\nIgloo House Door Type: %s\n", iglooHouse.doorType) fmt.Printf("Igloo House Window Type: %s\n", iglooHouse.windowType) fmt.Printf("Igloo House Num Floor: %d\n", iglooHouse.floor) } output.txt: 실행 결과
Normal House Door Type: Wooden Door Normal House Window Type: Wooden Window Normal House Num Floor: 2 Igloo House Door Type: Snow Door Igloo House Window Type: Snow Window Igloo House Num Floor: 1