设计模式——装饰器模式(Golang)
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
应用场景
- 当不能用继承的方式来扩展功能时;或者要扩展的功能比较多,而且这些功能每一种组合都要实现时,用装饰器模式很显然更简单。
- 当对象的功能要求可以动态地添加,也可以再动态地撤销时。
模式结构
装饰模式主要包含以下角色:
- 抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象。
- 具体构件(Concrete Component)角色:实现抽象构件,通过装饰角色为其添加一些职责。
- 抽象装饰(Decorator)角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
- 具体装饰(ConcreteDecorator)角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。
使用示例
1、执行特定函数时,额外添加相关操作(如:日志,时间等)
func Myfunction() {
fmt.Printf("这是一个输出函数!\n")
}
//装饰器函数,在特定的函数MyFunction执行前后,添加执行时间
func DecoratorFunction(a func()) {
fmt.Printf("StartTime: %v\n",time.Now())
a()
fmt.Printf("EndtTime: %v\n",time.Now())
}
func main() {
DecoratorFunction(Myfunction)
}
2、对特定的结构体动态新增额外信息装饰(如:BorderCollie结构体添加DogFood、DogCloth装饰)
//抽象构件
type AbstractDog interface {
GetName() string
GetPrice() float64
}
//具体构件
type BorderCollie struct {
}
func (b *BorderCollie) GetName() string{
return "边牧"
}
func (b *BorderCollie) GetPrice() float64{
return 2600
}
//抽象装饰角色
type DogDecorator struct {
borderCollie BorderCollie
}
//具体装饰A
type DogFood struct {
dog DogDecorator
}
func (f *DogFood) GetName() string {
return f.dog.borderCollie.GetName()+"狗粮"
}
func (f *DogFood) GetPrice() float64 {
return f.dog.borderCollie.GetPrice()+100
}
//具体装饰B
type DogCloth struct {
dog DogDecorator
}
func (f *DogCloth) GetName() string {
return f.dog.borderCollie.GetName()+"衣服"
}
func (f *DogCloth) GetPrice() float64 {
return f.dog.borderCollie.GetPrice()+150
}
func main() {
dogfood := new(DogFood)
dogcloth := new(DogCloth)
fmt.Printf("%v, %v\n",dogfood.GetName(),dogfood.GetPrice())
fmt.Printf("%v, %v\n",dogcloth.GetName(),dogcloth.GetPrice())
}
3、将特定函数作为参数,对该函数添加装饰器,以动态实现不同功能需求
type StringManipulator func(string) string
//装饰器函数A
func Tolower(m StringManipulator) StringManipulator {
return func(s string) string {
lower := strings.ToLower(s)
return lower
}
}
//装饰器函数B
func ToUpper(m StringManipulator) StringManipulator {
return func(s string) string {
upper := strings.ToUpper(s)
return upper
}
}
func main() {
str := *new(StringManipulator)
str = Tolower(str)
fmt.Printf("%v\n",str("THIS IS DECORATOR DEMO"))
str = ToUpper(str)
fmt.Printf("%v\n",str("this is decorator demo"))
}
优缺点
优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
缺点:多层装饰比较复杂。