๋นŒ๋” ํŒจํ„ด ๐Ÿ‘ท๐Ÿฝโ€โ™‚๏ธ

13164 ๋‹จ์–ด gowebdev100daysofcodetutorial
๋นŒ๋” ํŒจํ„ด์€ ์ฐฝ์กฐ์ ์ธ ๋””์ž์ธ ํŒจํ„ด์ž…๋‹ˆ๋‹ค. ์ œํ’ˆ ์ƒ์„ฑ์— ์—ฌ๋Ÿฌ ๋…๋ฆฝ์ ์ธ ๋‹จ๊ณ„๊ฐ€ ํฌํ•จ๋  ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

"์ œ์ž‘"ํ•˜๊ธฐ ์œ„ํ•ด ์—ฌ๋Ÿฌ ๋‹จ๊ณ„๊ฐ€ ํ•„์š”ํ•œ ๊ฒƒ์„ ์ƒ๊ฐํ•  ๋•Œ ์ฆ‰์‹œ ๋งˆ์Œ์— ๋– ์˜ค๋ฅด๋Š” ํ•œ ๊ฐ€์ง€๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? ๋ฐ”๋กœ, ์ง€ํ•˜์ฒ !! ๐Ÿฅ™๐Ÿคค
๋นต์„ ์„ ํƒํ•˜๊ณ  ์น˜์ฆˆ๋ฅผ ์„ ํƒํ•˜๊ณ  ํ† ํ•‘์„ ์„ ํƒํ•˜๊ณ  ๋งˆ์ง€๋ง‰์œผ๋กœ ์†Œ์Šค๋ฅผ ์„ ํƒํ•˜์‹ญ์‹œ์˜ค!

์„œ๋ธŒ๋ฅผ ๋งŒ๋“œ๋Š” ๊ณผ์ •์„ ์ดํ•ดํ•˜์…จ์œผ๋ฆฌ๋ผ ๋ฏฟ์Šต๋‹ˆ๋‹ค. ๋นŒ๋” ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜์—ฌ ์ฝ”๋”ฉํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ณด์ด๋Š”์ง€ ๋ด…์‹œ๋‹ค.

์ง€ํ•˜์ฒ  ์˜ˆ



ํ•˜์œ„ ๋ฉ”๋‰ด์ธ Veggie Delight์™€ ์น˜ํ‚จ ๋ฐ๋ฆฌ์•ผ๋ผ์˜ 2๊ฐ€์ง€ ๋‹ค๋ฅธ ์œ ํ˜•(๋ ˆ์‹œํ”ผ)์ด ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด๋“ค ๊ฐ๊ฐ์—๋Š” ์ „์šฉ "๋นŒ๋”"๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๋นŒ๋”๊ฐ€ ๊ตฌํ˜„ํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋™์ผํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ฉ”๋‰ด์— ๋” ๋งŽ์€ ์œ ํ˜•(๋ ˆ์‹œํ”ผ)์„ ์‰ฝ๊ฒŒ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

type sub struct {
    bread string
    hasCheese bool
    toppings []string
    sauces []string
}



type iSubBuilder interface {
    setBread()
    setCheese()
    setToppings()
    setSauces()
    getSub() sub
}



type veggieDelightBuilder struct {
    sub
}

func (v *veggieDelightBuilder) setBread() {
    v.sub.bread = "parmesan oregano"
}

func (v *veggieDelightBuilder) setCheese() {
    v.sub.hasCheese = false
}

func (v *veggieDelightBuilder) setToppings() {
    v.sub.toppings = []string{"olives", "tomatoes", "onions", "jalapeรฑos"}
}

func (v *veggieDelightBuilder) setSauces() {
    v.sub.sauces = []string{"south west"}
}

func (v *veggieDelightBuilder) getSub() sub {
    return v.sub
}



type chickenTeriyakiBuilder struct {
    sub
}

func (c *chickenTeriyakiBuilder) setBread() {
    c.sub.bread = "italian"
}

func (c *chickenTeriyakiBuilder) setCheese() {
    c.sub.hasCheese = true
}

func (c *chickenTeriyakiBuilder) setToppings() {
    c.sub.toppings = []string{"roasted chicken", "olives", "onions", "jalapeรฑos"}
}

func (c *chickenTeriyakiBuilder) setSauces() {
    c.sub.sauces = []string{"chilli", "bbq"}
}

func (c *chickenTeriyakiBuilder) getSub() sub {
    return c.sub
}

์„œ๋ธŒ์™€ ๋นŒ๋”๋ฅผ ์„ฑ๊ณต์ ์œผ๋กœ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ๋ณด์…จ๊ฒ ์ง€๋งŒ ๋‹ค๋ฅธ ๋ ˆ์‹œํ”ผ๋ฅผ ์‰ฝ๊ฒŒ ์ƒ์„ฑํ•˜๊ณ  ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด์ œ ๋นŒ๋”๋ฅผ ์ˆ˜๋ฝํ•˜๊ณ  ์šฐ๋ฆฌ๋ฅผ ์œ„ํ•ด ์„œ๋ธŒ๋ฅผ ๋นŒ๋“œํ•˜๋Š” ์„ ํƒ์  director ๊ตฌ์กฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

The director is not always part of the builder pattern. You could look at it as an added layer of abstraction for cleaner code



type director struct {
    builder iSubBuilder
}

func (d *director) setBuilder(builder iSubBuilder) {
    d.builder = builder
}

func (d *director) buildSub() sub {
    d.builder.setBread()
    d.builder.setCheese()
    d.builder.setToppings()
    d.builder.setSauces()

    return d.builder.getSub()
}

์™€ ๋ ๐ŸŽ‰

ํ–‰๋™์œผ๋กœ ๋ด…์‹œ๋‹ค:

func describeSub(sub sub) {
    fmt.Printf("bread: %s, cheese: %t, toppings: %s, sauces: %s\n", sub.bread, sub.hasCheese, strings.Join(sub.toppings, ", "), strings.Join(sub.sauces, ", "))
}

func main() {
    veggieDelight := &veggieDelightBuilder{}
    director := &director {
        builder: veggieDelight,
    }
    veggieDelightSub := director.buildSub()
    describeSub(veggieDelightSub)

    fmt.Println("------------")

    director.setBuilder(&chickenTeriyakiBuilder{})
    chickenTeriyakiSub := director.buildSub()

    describeSub(chickenTeriyakiSub)
}

์ด ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•˜๋ฉด ํ„ฐ๋ฏธ๋„์—์„œ ์ด๊ฒƒ์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

bread: parmesan oregano, cheese: false, toppings: olives, tomatoes, onions, jalapeรฑos, sauces: south west
------------
bread: italian, cheese: true, toppings: roasted chicken, olives, onions, jalapeรฑos, sauces: chilli, bbq

์ด ํŠœํ† ๋ฆฌ์–ผ์˜ ๋ชจ๋“  ์ฝ”๋“œ๋Š” this github repo์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋นŒ๋” ํŒจํ„ด์„ ๋” ์‰ฝ๊ฒŒ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค ๐Ÿš€

๊ฑด๋ฐฐ โ˜•๏ธ

์ข‹์€ ์›นํŽ˜์ด์ง€ ์ฆ๊ฒจ์ฐพ๊ธฐ