GoLang设计模式21|GoLang设计模式21 - 装饰模式
装饰器模式是一种结构型设计模式。通过装饰器模式可以为一个对象添加额外的功能而不需对其作出调整。
还是通过具体的案例来了解装饰器模式:假设我们开了一家披萨店,现在店里主营两款披萨:
- 素食狂披萨(Veggie Mania Pizza)
- 活力豆腐披萨(Peppy Tofu pizza)
package maintype pizza interface { getPrice() int }
然后需要这两款披萨分别创建一个struct并实现
getPrice()
函数来返回价格。因为定义了getPrice()
函数,因此这两款披萨的struct可以视为实现了pizza
接口。现在又有了一些变化:我们为设计了一些特色配料,这些配料也是需要收费的。这样我们需要修改下之前的
pizza
接口,通过装饰器的形式将配料(topping
)的信息给加进去。当前已有的配料为:- 番茄酱(TomatoTopping)
- 奶酪(CheeseTopping)
- 素食狂披萨 + 番茄酱
- 素食狂披萨 + 奶酪
- 不加任何配料的素食狂披萨
- 活力豆腐披萨 + 番茄酱
- ...
pizza
接口并嵌入一个pizza
接口的实例。现在每种披萨以及每种配料都有一个独立的struct了。每种披萨和配料都有各自的价格。当为披萨添加配料的时候,只需要在披萨的价格的基础上加上配料的价格就可以计算出最终的价格。
现在可以看到装饰器模式的作用了:我们不需要对
pizza
struct做任何调整,只是在pizza
对象的基础上做了一些装饰就得到了最终的价格。在这个过程中pizza
struct不知道 topping
struct的任何信息,只知道自己的价格。下面是装饰器模型的UML类图:
类图中ConcreteComponent(VeggieMania和PeppyTofu)和ConcreteDecorator(Topping)都实现了Component接口(Pizza),并且ConcreteDecorator还嵌入了一个Component接口的一个实例。
对比我们前面的例子:
pizza
接口是图中的ComponentveggieMania
和peppyPanner
是图中的ConcreteComponent,他们都实现了pizza
接口- ConcreteDecorator的代表是
cheeseTopping
和tomatoTopping
,它们也都实现了pizza
接口,同时它们也都嵌入了一个pizza
接口的实例
pizza.go
type pizza interface { getPrice() int }
peppyTofu.go
type peppyTofu struct { }func (p *peppyTofu) getPrice() int { return 20 }
【GoLang设计模式21|GoLang设计模式21 - 装饰模式】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!!!
推荐阅读
- C++设计模式中的观察者模式一起来看看
- 『德不孤』Pytest框架|『德不孤』Pytest框架 — 12、Pytest中Fixture装饰器(二)
- 『德不孤』Pytest框架|『德不孤』Pytest框架 — 11、Pytest中Fixture装饰器(一)
- [Golang]力扣Leetcode—剑指Offer—数组—47.礼物的最大价值(前缀和)
- 设计模式|里氏替换原则(爱恨纠葛的父子关系)
- Golang 基础之基础语法梳理 (三)
- Java设计模式七大原则之依赖倒置原则详解
- Python学习之装饰器与类的装饰器详解
- Go语言|【Golang】做算法题可能会用到的知识
- Golang 基础之基础语法梳理 (二)