1
0
Fork 0
mirror of https://github.com/tmrts/go-patterns.git synced 2025-04-03 13:13:34 +03:00

Builder pattern

added example code
updated readme (code and usage example)
This commit is contained in:
Oleg Butuzov 2018-02-18 15:49:46 +02:00
parent f978e42036
commit 46d93d5b47
3 changed files with 300 additions and 24 deletions

25
creational/builder.go Normal file
View file

@ -0,0 +1,25 @@
package main
import (
"fmt"
"./builder"
)
func main() {
assembly := car.NewAssembly(&car.Car{}).Color(car.RedColor)
familyCar := assembly.Wheels(car.SteelWheels).TopSpeed(50 * car.MPH).Build()
familyCar.Drive()
fmt.Printf("%#v\n", familyCar)
fmt.Printf("%#s\n", familyCar)
sportsCar := assembly.Wheels(car.SportsWheels).TopSpeed(150 * car.MPH).Build()
sportsCar.Drive()
fmt.Printf("%#v\n", sportsCar)
fmt.Printf("%#s\n", sportsCar)
}

View file

@ -13,49 +13,159 @@ however passing a struct to the builder method fills the code with boilerplate
```go
package car
type Speed float64
const (
MPH Speed = 1
KPH = 1.60934
import (
"fmt"
"log"
"strings"
)
type Color string
type (
// Color is string representation of Vihicle color
Color string
const (
BlueColor Color = "blue"
GreenColor = "green"
RedColor = "red"
// Wheels is int representation of Vihicle wheels number
Wheels string
// Speed is string representation of Vihicle top speed
// representation in miles per hour
Speed float64
)
type Wheels string
// Used constants definition
// Type Wheels enum
const (
SportsWheels Wheels = "sports"
SteelWheels = "steel"
SportsWheels Wheels = "sports"
SteelWheels = "steel"
)
type Builder interface {
Color(Color) Builder
Wheels(Wheels) Builder
TopSpeed(Speed) Builder
Build() Interface
// Type Color Enum
const (
BlueColor Color = "blue"
GreenColor = "green"
RedColor = "red"
)
// Speed constants for easy spead conversation
const (
MPH Speed = 1
KPH = 1.60934
)
type Car struct {
color Color
wheels Wheels
speed Speed
}
type Interface interface {
Drive() error
Stop() error
// Assembly is Assembly line struct that
// implement Builder interface
type Assembly struct {
v *Car
}
type Builder interface {
Color(Color) Builder
Wheels(Wheels) Builder
TopSpeed(Speed) Builder
Build() Vihicle
}
// Stoper for Stop implementation and intefae segregation
type Stoper interface {
Stop()
}
// Driver for Drive implementation and interface segregation
type Driver interface {
Drive()
}
// Vihicle interface to clarify what is vihicle:
// - is it drives and if its stops its vihicle
type Vihicle interface {
Stoper
Driver
}
// Vihicle interface implementation
// Drive is driving the car
func (c Car) Drive() {
fmt.Println("Car drives")
}
// Stop stops the car.
func (c Car) Stop() {
fmt.Println("Car stops")
}
func (c Car) String() string {
var color string
if c.color != "" {
color = fmt.Sprintf("%s Car", strings.Title(string(c.color)))
} else {
color = "(Soon to be rusty) Car"
}
return fmt.Sprintf("%s on %s wheels with top speed %.2f mph", color, c.wheels, c.speed)
}
// Builder interface implementation
// NewAssembly to create new Assembly line instance
func NewAssembly(vihicle *Car) *Assembly {
return &Assembly{v: vihicle}
}
// Color building color option of car in assembly line.
func (a *Assembly) Color(color Color) *Assembly {
a.v.color = color
return a
}
// Speed building speed option of car in assembly line.
func (a *Assembly) TopSpeed(speed Speed) *Assembly {
if speed <= 0.0 {
log.Fatal("Final Product wouldn't be able to implement Drive interface")
}
if speed > 276.0 {
log.Fatal("Mister Musk, stop doing that, Tesla 3 fastest in the space, but not in on the earth")
}
a.v.speed = speed
return a
}
// Wheels building wheels option of car in assembly line.
func (a *Assembly) Wheels(wheels Wheels) *Assembly {
a.v.wheels = wheels
return a
}
// Build interface Implementation
func (a Assembly) Build() Vihicle {
return a.v
}
```
## Usage
```go
assembly := car.NewBuilder().Paint(car.RedColor)
assembly := car.NewAssembly(&car.Car{}).Color(car.RedColor)
familyCar := assembly.Wheels(car.SportsWheels).TopSpeed(50 * car.MPH).Build()
familyCar := assembly.Wheels(car.SteelWheels).TopSpeed(50 * car.MPH).Build()
familyCar.Drive()
sportsCar := assembly.Wheels(car.SteelWheels).TopSpeed(150 * car.MPH).Build()
fmt.Printf("%#v\n", familyCar)
fmt.Printf("%#s\n", familyCar)
sportsCar := assembly.Wheels(car.SportsWheels).TopSpeed(150 * car.MPH).Build()
sportsCar.Drive()
fmt.Printf("%#v\n", sportsCar)
fmt.Printf("%#s\n", sportsCar)
```

141
creational/builder/car.go Normal file
View file

@ -0,0 +1,141 @@
package car
import (
"fmt"
"log"
"strings"
)
const Version = 1
type (
// Color is string representation of Vihicle color
Color string
// Wheels is int representation of Vihicle wheels number
Wheels string
// Speed is string representation of Vihicle top speed
// representation in miles per hour
Speed float64
)
// Used constants definition
// Type WheelsType enum
const (
SportsWheels Wheels = "sports"
SteelWheels = "steel"
)
// Type Color Enum
const (
BlueColor Color = "blue"
GreenColor = "green"
RedColor = "red"
)
// Speed constants for easy spead conversation
const (
MPH Speed = 1
KPH = 1.60934
)
type Car struct {
color Color
wheels Wheels
speed Speed
}
// Assembly is Assembly line struct that
// implement Builder interface
type Assembly struct {
v *Car
}
type Builder interface {
Color(Color) Builder
Wheels(Wheels) Builder
TopSpeed(Speed) Builder
Build() Vihicle
}
// Stoper for Stop implementation and intefae segregation
type Stoper interface {
Stop()
}
// Driver for Drive implementation and interface segregation
type Driver interface {
Drive()
}
// Vihicle interface to clarify what is vihicle:
// - is it drives and if its stops its vihicle
type Vihicle interface {
Stoper
Driver
}
// Vihicle interface implementation
// Drive is driving the car
func (c Car) Drive() {
fmt.Println("Car drives")
}
// Stop stops the car.
func (c Car) Stop() {
fmt.Println("Car stops")
}
func (c Car) String() string {
var color string
if c.color != "" {
color = fmt.Sprintf("%s Car", strings.Title(string(c.color)))
} else {
color = "(Soon to be rusty) Car"
}
return fmt.Sprintf("%s on %s wheels with top speed %.2f mph", color, c.wheels, c.speed)
}
// Builder interface implementation
// NewAssembly to create new Assembly line instance
func NewAssembly(vihicle *Car) *Assembly {
return &Assembly{v: vihicle}
}
// Color building color option of car in assembly line.
func (a *Assembly) Color(color Color) *Assembly {
a.v.color = color
return a
}
// Speed building speed option of car in assembly line.
func (a *Assembly) TopSpeed(speed Speed) *Assembly {
if speed <= 0.0 {
log.Fatal("Final Product wouldn't be able to implement Drive interface")
}
if speed > 276.0 {
log.Fatal("Mister Musk, stop doing that, Tesla 3 fastest in the space, but not in on the earth")
}
a.v.speed = speed
return a
}
// Wheels building wheels option of car in assembly line.
func (a *Assembly) Wheels(wheels Wheels) *Assembly {
a.v.wheels = wheels
return a
}
// Build interface Implementation
func (a Assembly) Build() Vihicle {
return a.v
}