装饰模式(Decorator)

First Post:

Last Update:

装饰模式(Decorator)

装饰模式(Decorator),动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。

装饰模式结构图

Component是定义一个对象接口,可以给这些对象动态地添加职责。
ConcentrateComponent是定义了一个具体的对象,也可以给这个对象添加职责。
Decorator,装饰抽象类,继承了Component,从外类来拓展Component类的功能,但对于Component来说,是无需了解Decorator的存在的。
ConcentrateDecorator类就是具体的装饰对象,起到给Component添加职责的功能。

装饰模式代码结构

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
71
72
Component类
abstract class Component()
{
public abstract void Operation();
}


ConcentrateComponent类
class ConcentrateComponentComponent
{
public override void Operation()
{
//具体对象的操作
}
}


Dectorator类
Class Dectorator : Component
{
protected Component component;
public void setComponent(Component component)
{//设置Component
this.component = component;
}
public override void Operation( )
{
if(component!=null)
{
component.Operation( );
}
}
}

ConcentrateDecoratorA类
class ConcentrateDecoratorA : Decrator
{
public override void Operation( )
{
base.Operation( );
//首先运行Component的Operation,
//再执行本类功能,相当于对Component添加了装饰
addedState = "newState";
//扩展逻辑——在原有的操作上面
}

}

ConcentrateDecoratorB类
class ConcentrateDecoratorB : Decrator
{
public override void Operation( )
{
base.Operation( );
AddBehaviour( );
}

public void AddBehaviour( )
{
//do sthing
}
}

//主函数中调用
//Dectorator dectorator = new Dectorator( );
//和Component一样是不用知道它的存在的
ConcentrateDecoratorA d1 = new ConcentrateDecoratorA();
ConcentrateDecoratorB d2 = new ConcentrateDecoratorB();
ConcentrateComponent cc = new ConcentrateComponent( );
cc.setComponent(d1);
d1.setComponent(d2);
d2.Operation( );

装饰的方法是:首先用ConcentrateComponent实例化对象cc,然后用ConcentrateDecoratorA实例化对象d1来包装cc,再用ConcentrateDecoratorB实例化对象d2来包装d1,最终执行d2的Operation();最终所有的Operation都会被执行,相当于在Component外拓展了功能。

装饰模式中装饰类的顺序:装饰模式是利用SetComponent来对对象进行包装的,这样,每个装饰对象的实现就和如何使用这个对象分离开了,每个装饰对象只关心自己的功能,不需要关心如何被添加到对象链里面。完全可以调换调用的顺序。

如果只有一个ConcentrateComponent类而没有抽象的Component类,那么Dectorator类可以是ConcentrateComponent的一个子类。同理,如果只有一个ConcentrateDecorator类,无需单独建立一个单独的Decorator类,而把Decorator和ConcentrateDecorator的责任合并成一个类。

问题和总结

装饰模式是为已有功能动态地添加更多功能的一种方式。

什么时候用装饰模式呢?

在起初的设计中,当系统需要新功能时,是向旧的类中添加新的代码。这些新加的代码通常装饰了原有类的核心职责或主要行为。这种设计的问题在于,它们在主类中添加了新的字段,新的方法和新的逻辑,从而增加了主类的复杂度。
当新加入的东西只是为了满足某些方面特定情况下采用的特殊行为的需要时,可以用装饰模式将要装饰的功能放在单独的类中,让这个类包装它要装饰的对象,因此,当需要执行特殊行为时,客户端代码就可以在运行时根据需求选择性地、按顺序地使用装饰功能包装对象。

装饰模式优点

把类中的装饰功能能类中搬移去除,这样可以简化原有的类。
有效地把类的核心职责和装饰功能区分开了。而且可以去除其中重复的装饰逻辑。