装饰模式
# 分类
结构型模式
# 定义
- 装饰模式(Decorator Pattern) 允许向一个现有对象添加新功能,同时又不改变其结构。这种模式创建了一个装饰类,用来
包装原有的类
,并在保持类方法签名完整的前提下,提供了额外的功能
。
# 意图
- 动态地给一个对象添加一些额外职责,就增加功能来说,
装饰器模式相比生成子类更为灵活
。
# 应用场景
- 扩展一个类的功能。
- 动态增加、撤销功能。
应用案例
- 孙悟空有72变,当他变成庙宇后,他的根本还是一只猴子,但他又有了庙宇的功能。
- 不论一幅画有没有画框都可以挂在墙上,但是通常都是有画框的,并且实际上是画框被挂在墙上。在挂在墙上之前,画可以被蒙上玻璃,装订到框子里,这时画、玻璃和画框形成了一个物体。
# 角色与结构图
- Component:
抽象组件角色
定义一个接口。 - ConcreteComponent:
具体组件角色
实现了抽象组件接口。 - Decorator:
抽象装饰器角色
实现了抽象组件接口同时包装一个具体组件对象。 - ConcreteDecorator:
具体抽象装饰器角色
实现了抽象装饰器中方法,并添加新的功能。 - Client:
客户程序角色
使用组件和装饰器添加新功能。
下图解释了装饰模式中各角色的作用

# 示例代码
//定义对象接口,用来动态添加职责
abstract class Component{
public abstract void Operation();
}
//具体对象
class ConcreteComponent : Component{
public override void Operation(){
Console.WriteLine("执行具体对象的操作!");
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
//抽象装饰类
abstract class Decorator : Component{
protected Component component;
public void SetComponent(Component component){
this.component = component;
}
public override void Operation(){
if(component!=null){
this.Component.Operation();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
//具体装饰类
class ConcreteDecoratorA : Decorator{
private string addedState;
public override void Operation(){
base.Operation();
addedState = "New state";
Console.WriteLine("具体装饰对象A的操作");
}
}
class ConcreteDecoratorB : Decorator{
public override void Operation(){
base.Operation();
AddedBehavior();
Console.WriteLine("具体装饰对象B的操作");
}
private void AddedBehavior(){
Console.WriteLine("添加一个新动作");
}
}
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//客户端
class Client{
static void Main(String[] args){
ConcreteComponent c = new ConcreteComponent();
ConcreteDecoratorA d1 = new ConcreteDecoratorA();
ConcreteDecoratorB d2 = new ConcreteDecoratorB();
d1.SetComponent(c);
d2.SetComponent(d1);
d2.Operation();
Console.ReadLine();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
// 其他例子
namespace StructuralPattern
{
// 装饰器设计模式
class Decorator
{
public static void Main()
{
ShapeDecorator decorator = new RedShapDecorator(new Rectangle());
decorator.Draw();
Console.ReadKey();
}
}
// 定义一个形状接口
public interface Shape
{
void Draw();
}
// 矩形
public class Rectangle : Shape
{
public void Draw()
{
Console.WriteLine("绘制了一个矩形");
}
}
// 圆形
public class Circle : Shape
{
public void Draw()
{
Console.WriteLine("绘制了一个圆形");
}
}
// 定义一个实现了Shape接口的shape装饰器
public abstract class ShapeDecorator : Shape
{
protected Shape shape;
public virtual void Draw()
{
this.shape.Draw();
}
}
// 定义了一个具体的红色形状装饰器类
public class RedShapDecorator : ShapeDecorator
{
public RedShapDecorator(Shape shape)
{
this.shape = shape;
}
public override void Draw()
{
base.Draw();
//装饰器添加了边框,扩展了绘图功能
this.SetBorder(shape);
}
private void SetBorder(Shape shape)
{
Console.WriteLine("给形状添加个红色边框功能!");
}
}
}
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# 优点
- 把类中的装饰功能从类中搬移去除,这样可以简化原有的类。这样有效的把类的核心职责和装饰功能区分开来,而且可以去除相关类中复杂的装饰逻辑。
- 装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
# 缺点
- 多层装饰比较复杂。
# 小结
- 装饰模式是利用 SetComponent 来对对象进行包装的,这样每个装饰对象的实现就和使用这个装饰对象分离开了。每个装饰对象只关心自己的功能,不需要关心如何被添加到对象链当中。
- 装饰模式是为已有功能动态的添加更多功能的一种方式。
- 当系统需要新功能的时候,是向旧的类中添加新代码,这些新加的代码通常装饰了原有类的核心职责或主要行为。装饰模式提供了一种非常好的解决方案,它把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象,因此,当需要执行特殊行为时,客户代码就可以根据需要有选择地、按顺序地使用装饰功能包装对象了。
- 主要解决?一般的,我们为了扩大一个类经常使用继承的方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。
- 何时使用?在不想增加很多子类的情况下扩展类。
- 如何解决?将具体功能职责划分,同时继承装饰者模式。
- 注意:可代替继承。
# 一句话概括
动态的给对象添加新功能。
编辑 (opens new window)
上次更新: 2025/03/22, 13:47:44