๋น๋ ํจํด ๐ท๐ฝโโ๏ธ
"์ ์"ํ๊ธฐ ์ํด ์ฌ๋ฌ ๋จ๊ณ๊ฐ ํ์ํ ๊ฒ์ ์๊ฐํ ๋ ์ฆ์ ๋ง์์ ๋ ์ค๋ฅด๋ ํ ๊ฐ์ง๋ ๋ฌด์์ ๋๊น? ๋ฐ๋ก, ์งํ์ฒ !! ๐ฅ๐คค
๋นต์ ์ ํํ๊ณ ์น์ฆ๋ฅผ ์ ํํ๊ณ ํ ํ์ ์ ํํ๊ณ ๋ง์ง๋ง์ผ๋ก ์์ค๋ฅผ ์ ํํ์ญ์์ค!
์๋ธ๋ฅผ ๋ง๋๋ ๊ณผ์ ์ ์ดํดํ์ จ์ผ๋ฆฌ๋ผ ๋ฏฟ์ต๋๋ค. ๋น๋ ํจํด์ ์ฌ์ฉํ์ฌ ์ฝ๋ฉํ๋ฉด ์ด๋ป๊ฒ ๋ณด์ด๋์ง ๋ด ์๋ค.
์งํ์ฒ ์
ํ์ ๋ฉ๋ด์ธ 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์์ ์ฐพ์ ์ ์์ต๋๋ค.
๋น๋ ํจํด์ ๋ ์ฝ๊ฒ ์ดํดํ ์ ์๊ธฐ๋ฅผ ๋ฐ๋๋๋ค ๐
๊ฑด๋ฐฐ โ๏ธ
Reference
์ด ๋ฌธ์ ์ ๊ดํ์ฌ(๋น๋ ํจํด ๐ท๐ฝโโ๏ธ), ์ฐ๋ฆฌ๋ ์ด๊ณณ์์ ๋ ๋ง์ ์๋ฃ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ๋งํฌ๋ฅผ ํด๋ฆญํ์ฌ ๋ณด์๋ค https://dev.to/shubhamzanwar/builder-pattern-5839ํ ์คํธ๋ฅผ ์์ ๋กญ๊ฒ ๊ณต์ ํ๊ฑฐ๋ ๋ณต์ฌํ ์ ์์ต๋๋ค.ํ์ง๋ง ์ด ๋ฌธ์์ URL์ ์ฐธ์กฐ URL๋ก ๋จ๊ฒจ ๋์ญ์์ค.
์ฐ์ํ ๊ฐ๋ฐ์ ์ฝํ ์ธ ๋ฐ๊ฒฌ์ ์ ๋ (Collection and Share based on the CC Protocol.)
์ข์ ์นํ์ด์ง ์ฆ๊ฒจ์ฐพ๊ธฐ
๊ฐ๋ฐ์ ์ฐ์ ์ฌ์ดํธ ์์ง
๊ฐ๋ฐ์๊ฐ ์์์ผ ํ ํ์ ์ฌ์ดํธ 100์ ์ถ์ฒ ์ฐ๋ฆฌ๋ ๋น์ ์ ์ํด 100๊ฐ์ ์์ฃผ ์ฌ์ฉํ๋ ๊ฐ๋ฐ์ ํ์ต ์ฌ์ดํธ๋ฅผ ์ ๋ฆฌํ์ต๋๋ค