go-patterns icon indicating copy to clipboard operation
go-patterns copied to clipboard

Builder Pattern missing parts

Open gcstang opened this issue 7 years ago • 4 comments

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...

gcstang avatar May 04 '18 19:05 gcstang

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

zsr228 avatar Jul 19 '18 07:07 zsr228

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.

benjaminapetersen avatar May 28 '19 14:05 benjaminapetersen

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

zhongqin0820 avatar Jun 06 '19 04:06 zhongqin0820

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

benjaminapetersen avatar Jun 06 '19 13:06 benjaminapetersen