装饰器模式(Decorator Pattern)

在python中有一个非常常用的语法糖@,本质上就是装饰器。这种模式可以不改变原文件的情况下动态的扩展一个对象的功能而不用创建子类,避免了类膨胀,是一种比较常用的模式,有个细节需要注意的就是装饰的顺序。

decorator.png

这个模式核心有4个角色:

  1. 被装饰者抽象Component:一个接口或者抽象类,定义最核心对象。
  2. 被装饰者具体实现ConcreteComponent:Component的实现类,装饰的就是这个实现类。
  3. 装饰者抽象Decorator:一般是个抽象类,实现接口或者抽象方法,里面必须有一个Component变量引用。
  4. 装饰者实现ConcreteDecorator:具体的装饰者类。

当只有一个被装饰者时,也可以吧Component和ConcreateComponent合并成一个,灵活运用而不要死板。

示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package main

import (
"fmt"
)

type Component interface {
show()
}

type ConcreteComponent struct {
name string
}

func (c ConcreteComponent) show() {
fmt.Printf("This is %s\n", c.name)
}

type Decorator struct {
c Component
}

func (d *Decorator) show() {
d.c.show()
}

func (d *Decorator) setComponent(com Component) {
d.c = com
}

type ConcreteDecorator struct {
d Decorator
age int
}

func (c *ConcreteDecorator) show() {
fmt.Printf("In ConcreteDecorator show func! im %d old!\n", c.age)
c.d.show()
}
func (c *ConcreteDecorator) setComponent(com Component) {
c.d.setComponent(com)
}

func main() {
c := ConcreteComponent{name: "tom"}
cd := ConcreteDecorator{age: 10}
cd.setComponent(c)
cd.show()
}

程序输出:

1
2
In ConcreteDecorator show func! im 10 old!
This is concrete_component

使用场景

  1. 当需要动态的对某个对象添加功能时。
  2. 当某个对象的功能经常发生变化时,又想避免过多的继承造成类膨胀。

对比

  1. 适配器模式:适配器模式将一种接口转换成另一种接口,而装饰者模式则是不改变原有的功能上增加新功能。
  2. 策略模式:切换运算法则的方式来变换功能。