GO设计模式——11、装饰器模式(结构型)
目录
装饰器模式(Decorator Pattern)
装饰器模式的核心角色:
优缺点
使用场景
代码实现
装饰器模式(Decorator Pattern)
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。装饰器模式通过将对象包装在装饰器类中,以便动态地修改其行为。这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
装饰器模式的核心角色:
- 抽象组件(Component):定义了对象的接口,可以是一个抽象类或接口。
- 具体组件(ConcreteComponent):实现了抽象组件的接口,是被装饰的对象。
- 装饰器(Decorator):维持一个指向抽象组件对象的引用,并实现了抽象组件的接口。
- 具体装饰器(ConcreteDecorator):具体的装饰器对象,用于扩展具体组件的功能。
优缺点
(1)优点:
- 装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
(2)缺点:多层装饰比较复杂。
使用场景
- 扩展一个类的功能。
- 动态增加功能,动态撤销。
代码实现
package main
import (
"fmt"
)
// 抽象组件:咖啡接口
type Coffee interface {
GetDescription() string
GetCost() float64
}
// 具体组件:原味咖啡
type PlainCoffee struct{}
func (c *PlainCoffee) GetDescription() string {
return "Plain Coffee"
}
func (c *PlainCoffee) GetCost() float64 {
return 1.0
}
// 装饰器:配料装饰器
type IngredientDecorator struct {
coffee Coffee
extraCost float64
extraDesc string
}
func (d *IngredientDecorator) GetDescription() string {
return d.coffee.GetDescription() + ", " + d.extraDesc
}
func (d *IngredientDecorator) GetCost() float64 {
return d.coffee.GetCost() + d.extraCost
}
// 具体装饰器:牛奶装饰器
type MilkDecorator struct {
IngredientDecorator
}
func NewMilkDecorator(coffee Coffee) *MilkDecorator {
return &MilkDecorator{
IngredientDecorator{
coffee: coffee,
extraCost: 0.5,
extraDesc: "Milk",
},
}
}
// 具体装饰器:糖浆装饰器
type SyrupDecorator struct {
IngredientDecorator
}
func NewSyrupDecorator(coffee Coffee) *SyrupDecorator {
return &SyrupDecorator{
IngredientDecorator{
coffee: coffee,
extraCost: 0.3,
extraDesc: "Syrup",
},
}
}
func main() {
coffee := &PlainCoffee{}
fmt.Println("Coffee:", coffee.GetDescription(), "Cost:", coffee.GetCost())
coffeeWithMilk := NewMilkDecorator(coffee)
fmt.Println("Coffee with Milk:", coffeeWithMilk.GetDescription(), "Cost:", coffeeWithMilk.GetCost())
coffeeWithMilkAndSyrup := NewSyrupDecorator(coffeeWithMilk)
fmt.Println("Coffee with Milk and Syrup:", coffeeWithMilkAndSyrup.GetDescription(), "Cost:", coffeeWithMilkAndSyrup.GetCost())
}