여러 단계로 나눠서 특정 객체를 만들 수 있도록 각 단계를 캡슐화할 수 있다. 유연한 디자인이 필요한 시점에 사용되며, 반복잡억을 별도의 객체로 캡슐화함으로써 컬렉션의 내부 구조를 클라이언트로 부터 보호할 수 있다. 만드는 일을 객체(빌더)에 캡슐화시켜서 클라이언트에서는 빌더한테 구조를 만들어 달라고 요청하기만 하면 되도록 만드는 것이다.
package builder
type BuildProcess interface {
SetWheels() BuildProcess
SetSeats() BuildProcess
SetStructure() BuildProcess
GetVehicle() VehicleProduct
} //해당 인터페이스의 함수를 구현한 구조체를 만든다.
//Product
type VehicleProduct struct {
Wheels int
Seats int
Structure string
} //인터페이스에 정의된 함수과정을 거진 결과물
//Director
type ManufacturingDiretor struct {
builder BuildProcess
}
func (m *ManufacturingDiretor) Construct() {
m.builder.SetSeats().SetStructure().SetWheels()
}
func (m *ManufacturingDiretor) SetBuilder(b BuildProcess) {
m.builder = b
} //빌더 인터페이스를 구현한 빌더 객체를 실행시켜 결과물을 내보낸다.
//A Builder of type Car
type CarBuilder struct {
v VehicleProduct
}
/*
각 단계별로 각 빌더마다 옵션 값을 넣고 리턴한다.
*/
func (c *CarBuilder) SetWheels() BuildProcess {
c.v.Wheels = 4
return c
}
func (c *CarBuilder) SetSeats() BuildProcess {
c.v.Seats = 4
return c
}
func (c *CarBuilder) SetStructure() BuildProcess {
c.v.Structure = "Car"
return c
}
func (c *CarBuilder) GetVehicle() VehicleProduct {
return c.v
} // 만들어진 결과물을 리턴
//A builder of type motobike
type BikeBuilder struct {
v VehicleProduct
}
/*
비슷한 유형의 객체 데이터의 세부 데이터만 조정하여 다양한 Type의 객체를
만들어 낸다.
*/
func (b *BikeBuilder) SetWheels() BuildProcess {
b.v.Wheels = 2
return b
}
func (b *BikeBuilder) SetSeats() BuildProcess {
b.v.Seats = 2
return b
}
func (b *BikeBuilder) SetStructure() BuildProcess {
b.v.Structure = "Motobike"
return b
}
func (b *BikeBuilder) GetVehicle() VehicleProduct {
return b.v
}
빌더의 장점은 다음과 같다.
단점으로는 복합 객체 구조를 위한 용도로 많이 쓰이며, 팩토리를 사용하는 경우에 비해 객체를 만들어 내기 위해 클라이언트에 대해 더 자세히 알아야 한다는 점이다.
이러한 Builder 패턴으로 구현한 GO의 내부 패키지로는 string.Builder가 있다.
func main() {
hello := "hello"
sb := strings.Builder{}
sb.WriteString("<p>")
sb.WriteString(hello)
sb.WriteString("</p>")
// 각기 다른 문장을 받아 객체를 만들어 낸다.
fmt.Printf("%s\\n", sb.String())
}