装饰模式是一种结构型设计模式, 允许在运行时动态地给对象添加新的行为。
更改一个对象的行为时,不能忽视继承可能引发的几个严重问题
- 继承是静态的,无法在运行时更改已有对象的行为, 只能使用由不同子类创建的对象替代当前的整个对象。
- 子类只能有一个父类。 大部分编程语言不允许一个类同时继承多个类的行为
业务逻辑
装饰模式通过将对象放入包装器中来实现这一点,每个包装器都提供了额外的功能。在装饰模式中,有四个角色:
- Component(抽象构件):定义了一个对象接口,可以给这些对象动态地添加职责。
- ConcreteComponent(具体构件):定义了一个具体的对象,也可以给这个对象添加一些职责。
- Decorator(装饰者):持有一个抽象构件的引用,并定义了一个与抽象构件接口一致的接口。
- ConcreteDecorator(具体装饰者):负责给具体构件添加额外的职责

代码实现
代码路径:https://github.com/XBoom/DesignPatterns/tree/main/09_Decorator
-
首先有一个具体的组件
ConcreteComponent
构建(这里为具体电池组件 凝聚态电池)1
2
3
4
5type BatteryComponent struct{}
func (c *BatteryComponent) Name() string {
return "Condensed Battery"
} -
Component
装饰构建类似封装一层,在ConcreteComponent
的基础上进一步拓展,那么就声明一个抽象组件(这里指电池)1
2
3
4// Battery 抽象构件,给这个对象动态地添加职责
type Battery interface {
Name() string
} -
装饰者
Decorator
则是在前面组件ConcreteComponent
的基础上拓展(这里举例汽车)1
2
3
4// Car 装饰者
type Car interface {
Run() string
} -
这里构建2 个具体装饰者
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17// BYD 具体装饰者 BYD
type BYD struct {
battery Battery
}
func (d *BYD) Run() string {
return "BYD use " + d.battery.Name() + " run"
}
// Tesla 具体装饰者 Tesla
type Tesla struct {
battery Battery
}
func (t *Tesla) Run() string {
return "Tesla use " + t.battery.Name() + " run"
}
单元测试
1 | var ExpectBattery = "Condensed Battery" |
适用场景
- 如果希望在无需修改代码的情况下即可使用对象,且希望在运行时为对象新增额外的行为,可以使用装饰模式。
- 如果用继承来扩展对象行为的方案难以实现或者根本不可行,你可以使用该模式
总结
- 无需创建新子类即可扩展对象的行为。
- 可以在运行时添加或删除对象的功能。
- 可以用多个装饰封装对象来组合几种行为。
- 单一职责原则。 可以将实现了许多不同行为的一个大类拆分为多个较小的类