装饰器模式 (Decorator Pattern)
意图
装饰器模式是结构型设计模式:把对象包进装饰器类,在不改原有类的前提下动态加职责。
问题
在现实世界中,考虑一个简单的文本编辑器。最基本的功能是显示文本,但有时需要为文本添加不同的效果,例如加粗、斜体或下划线。如果直接在文本类中添加这些功能,会导致类的复杂度增加,且不易维护和扩展。
解决方案
做法是为每种效果各写一个装饰器类,再按需要把它们层层包在文本对象外面。
模式结构
- 组件(Component):定义了将要动态添加职责的对象接口。
- 具体组件(Concrete Component):实现了组件接口,是将要被装饰的对象。
- 装饰器(Decorator):实现了组件接口,持有一个组件对象,并在其基础上扩展功能。
- 具体装饰器(Concrete Decorator):继承装饰器,并实现具体的装饰功能。
代码
装饰器模式的 Go 实现:
go
package main
import "fmt"
// 组件接口
type Component interface {
Operation() string
}
// 具体组件 - 文本
type Text struct {
content string
}
func (t *Text) Operation() string {
return t.content
}
// 装饰器基类
type Decorator struct {
component Component
}
func (d *Decorator) Operation() string {
if d.component != nil {
return d.component.Operation()
}
return ""
}
// 具体装饰器 - 加粗
type BoldDecorator struct {
Decorator
}
func (b *BoldDecorator) Operation() string {
return "<b>" + b.Decorator.Operation() + "</b>"
}
// 具体装饰器 - 斜体
type ItalicDecorator struct {
Decorator
}
func (i *ItalicDecorator) Operation() string {
return "<i>" + i.Decorator.Operation() + "</i>"
}
// 具体装饰器 - 下划线
type UnderlineDecorator struct {
Decorator
}
func (u *UnderlineDecorator) Operation() string {
return "<u>" + u.Decorator.Operation() + "</u>"
}
func main() {
text := &Text{content: "Hello, World!"}
boldText := &BoldDecorator{Decorator{component: text}}
italicBoldText := &ItalicDecorator{Decorator{component: boldText}}
underlinedItalicBoldText := &UnderlineDecorator{Decorator{component: italicBoldText}}
fmt.Println("原始文本:", text.Operation())
fmt.Println("加粗文本:", boldText.Operation())
fmt.Println("加粗斜体文本:", italicBoldText.Operation())
fmt.Println("加粗斜体下划线文本:", underlinedItalicBoldText.Operation())
}适用场景
- 需要在不改变原有类的情况下,动态地为对象添加职责时。
- 需要为一组对象添加相同的职责,且职责可以动态组合时。
实现方式
- 定义组件接口,声明将要动态添加职责的对象接口。
- 创建具体组件,实现组件接口。
- 创建装饰器基类,实现组件接口,并持有一个组件对象。
- 创建具体装饰器,继承装饰器基类,并实现具体的装饰功能。
- 在客户端代码中,通过装饰器类动态地为组件对象添加职责。
优缺点
优点:
- 动态地为对象添加新职责,而不影响其他对象。
- 可以通过多个装饰器组合,形成复杂的功能。
- 符合开闭原则,可以通过添加新的装饰器类来扩展系统,而不会影响现有代码。
缺点:
- 可能会导致大量的小类,增加系统的复杂度。
- 多个装饰器的组合可能会导致调试困难。
其他模式的关系
- 代理模式(Proxy Pattern):结构和装饰器类似,代理控制访问,装饰器加职责。
- 适配器模式(Adapter Pattern):适配器把一个接口换成另一个,装饰器不换接口,只加职责。
- 组合模式(Composite Pattern):组合把对象拼成树形结构表示“部分-整体”,装饰器是在单个对象外面层层包裹。