tmrts / go-patterns

Curated list of Go design patterns, recipes and idioms

Home Page:http://tmrts.com/go-patterns

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Builder Pattern missing parts

gcstang opened this issue · comments

commented

There are parts that you show in how to use the pattern that aren't in the example of creating it.

i.e. NewBuilder(), Paint(..), etc...

as @gcstang mentioned, builder pattern missing some code that we can't understand

Just ran into this as well. Looked promising, nice and clean, but it's incomplete. Once you get to this point:

assembly := car.NewBuilder().Paint(car.RedColor)

You'll have to go elsewhere to find the missing pieces.

According to the usage code. We should change Color(Color) Builder to Paint(Color) Builder. Thus,

type Builder interface {
	Paint(Color) Builder
	Wheels(Wheels) Builder
	TopSpeed(Speed) Builder
	Build() Interface
}

And the NewBuilder() should be:

func NewBuilder(b Builder) Builder {
	return b
}

Here, we assume that they are in the same package. Thus, the usage part should be:

import (
	"log"
	"testing"
)

// the implementation of Builder interface
type Car struct {
	color  Color
	wheels Wheels
	speed  Speed
}

func (c Car) Paint(color Color) Builder {
	c.color = color
	return c
}
func (c Car) Wheels(w Wheels) Builder {
	c.wheels = w
	return c
}
func (c Car) TopSpeed(s Speed) Builder {
	c.speed = s
	return c
}
func (c Car) Build() Interface {
	switch c.wheels {
	case SportsWheels:
		return SportsCar{}
	case SteelWheels:
		return FamilyCar{}
	}
	return nil
}

// the implementation of Interface interface
type FamilyCar struct{}

func (f FamilyCar) Drive() error {
	log.Println("FamilyCar Drive()")
	return nil
}
func (f FamilyCar) Stop() error {
	log.Println("FamilyCar Stop()")
	return nil
}

// the implementation of Interface interface
type SportsCar struct{}

func (s SportsCar) Drive() error {
	log.Println("SportsCar Drive()")
	return nil
}

func (s SportsCar) Stop() error {
	log.Println("SportsCar Stop()")
	return nil
}

// the testcase
func TestCarBuilder(t *testing.T) {
	assembly := NewBuilder(Car{}).Paint(RedColor)

	familyCar := assembly.Wheels(SportsWheels).TopSpeed(50 * MPH).Build()
	familyCar.Drive()
	familyCar.Stop()

	sportsCar := assembly.Wheels(SteelWheels).TopSpeed(150 * MPH).Build()
	sportsCar.Drive()
	sportsCar.Stop()

}

I also create a UML illustration of the demo code.

UML

Very nice! Possibly could fork & PR to get it included? If PR not accepted, your fork would still be an improvement.