Decorator Pattern
출처: https://golangbyexample.com/decorator-pattern-golang/
개요
개체를 변경하지 않고 기능을 추가할 수 있음.
=> 이미 테스트가 끝난 코드를 수정하면 안됨 (Open-Closed Principle에 위배됨)
두가지 피자가 존재한다고 가정해보자.
- vegge mania pizza
- peppy tofu pizza
UML 다이어그램
코드
pizza.go
package main
type pizza interface {
getPrice() int
}
peppyPaneer.go
package main
type peppyPaneer struct {
}
func (p *peppyPaneer) getPrice() int {
return 20
}
veggeMania.go
package main
type veggeMania struct {
}
func (p *veggeMania) getPrice() int {
return 15
}
토핑을 추가하기 위해 위쪽에 만들어진 구조체들은 더 이상 수정하면 안됨.
cheeseTopping.go
package main
type cheeseTopping struct {
pizza pizza
}
func (c *cheeseTopping) getPrice() int {
pizzaPrice := c.pizza.getPrice()
return pizzaPrice + 10
}
tomatoTopping.go
package main
type tomatoTopping struct {
pizza pizza
}
func (c *tomatoTopping) getPrice() int {
pizzaPrice := c.pizza.getPrice()
return pizzaPrice + 7
}
main.go
package main
import "fmt"
func main() {
veggiePizza := &veggeMania{}
//Add cheese topping
veggiePizzaWithCheese := &cheeseTopping{
pizza: veggiePizza,
}
//Add tomato topping
veggiePizzaWithCheeseAndTomato := &tomatoTopping{
pizza: veggiePizzaWithCheese,
}
fmt.Printf("Price of veggieMania pizza with tomato and cheese topping is %d\n", veggiePizzaWithCheeseAndTomato.getPrice())
peppyPaneerPizza := &peppyPaneer{}
//Add cheese topping
peppyPaneerPizzaWithCheese := &cheeseTopping{
pizza: peppyPaneerPizza,
}
fmt.Printf("Price of peppyPaneer with tomato and cheese topping is %d\n", peppyPaneerPizzaWithCheese.getPrice())
}
실행 결과
Price of veggieMania pizza with tomato and cheese topping is 32
Price of peppyPaneer with tomato and cheese topping is 30