装饰器模式是一种结构型设计模式。通过装饰器模式可以为一个对象添加额外的功能而不需对其作出调整。

还是通过具体的案例来了解装饰器模式:假设我们开了一家披萨店,现在店里主营两款披萨:

  • 素食狂披萨(Veggie Mania Pizza)
  • 活力豆腐披萨(Peppy Tofu pizza)

以上两款披萨有不同的价格,为获取价格需要定义这样一个接口:

package main

type pizza interface {
	getPrice() int
}
getPrice()getPrice()pizza
pizzatopping
  • 番茄酱(TomatoTopping)
  • 奶酪(CheeseTopping)

另外,我们也得注意,加了配料的披萨也是一种新的披萨,所以现在顾客有了更多的选择:

  • 素食狂披萨 + 番茄酱
  • 素食狂披萨 + 奶酪
  • 不加任何配料的素食狂披萨
  • 活力豆腐披萨 + 番茄酱
  • ...
pizzapizza

现在每种披萨以及每种配料都有一个独立的struct了。每种披萨和配料都有各自的价格。当为披萨添加配料的时候,只需要在披萨的价格的基础上加上配料的价格就可以计算出最终的价格。

pizzapizzapizzatopping

下面是装饰器模型的UML类图:

 

类图中ConcreteComponent(VeggieMania和PeppyTofu)和ConcreteDecorator(Topping)都实现了Component接口(Pizza),并且ConcreteDecorator还嵌入了一个Component接口的一个实例。

对比我们前面的例子:

pizzaveggieManiapeppyPannerpizzacheeseToppingtomatoToppingpizzapizza

来看看具体的代码吧:

pizza.go

type pizza interface {
	getPrice() int
}

peppyTofu.go

type peppyTofu struct {
}

func (p *peppyTofu) getPrice() int {
	return 20
}

veggeMania.go

type veggieMania struct {
}

func (p *veggieMania) getPrice() int {
	return 15
}

cheeseTopping.go

type cheeseTopping struct {
	pizza pizza
}

func (c *cheeseTopping) getPrice() int {
	pizzaPrice := c.pizza.getPrice()
	return pizzaPrice + 10
}

tomatoTopping.go

type tomatoTopping struct {
	pizza pizza
}

func (c *tomatoTopping) getPrice() int {
	pizzaPrice := c.pizza.getPrice()
	return pizzaPrice + 7
}

main.go

func main() {

	veggiePizza := &veggieMania{}

	//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())

	peppyTofuPizza := &peppyTofu{}

	//Add cheese topping
	peppyTofuPizzaWithCheese := &cheeseTopping{
		pizza: peppyTofuPizza,
	}

	fmt.Printf("Price of peppyTofu with tomato and cheese topping is %d\n", peppyTofuPizzaWithCheese.getPrice())

}

输出内容:

Price of veggieMania pizza with tomato and cheese topping is 32
Price of peppyTofu with tomato and cheese topping is 30

代码已上传至GitHub: zhyea / go-patterns / decorator-pattern

END!!!

 


仅是学习笔记,难免出错,望不吝指点 【文章原创作者:香港服务器 http://www.558idc.com/hk.html提供,感谢支持】