如何使“对象功能的扩展”能够根据需要来动态地实现?同时避免“扩展功能的增多”带来的子类膨胀的问题?从而使得任何“功能扩展变化”所导致的影响降为最低?
意图:
动态地给一个对象增加一些额外的职责。就增加功能而言,Decorator模式比生成子类更为灵活。
出自:《设计模式》GoF
Decorator模式的几个要点:
1、通过采用组合、而继承的手法,Decorator模式实现了在运行时动态地扩展对象功能的能力,而且可以根据需要扩展多个功能。避免了单独使用继承带来的“灵活性差”和“多子类衍生问题”。
2、Component类在Decorator模式中充当抽象接口的角色,不应该去实现具体的行为。而且Decorator类对于Component类应该透明--换言之Component类无需知道Decorator类,Decorator类是从外部来扩展Component类的功能。
3、Decorator类在接口上表现为is-a Component的继承关系,即Decorator类继承了Component类所具有的接口。但在实现上又表现为has-a Component的组合关系,即Decorator类又使用了另外一个Component类。我们可以使用一个或者多个Decorator对象来“装饰”一个Component对象,且装饰后的对象仍然是一个Component对象。
4、Decorator模式并非解决“多子类衍生的多继承”问题,Decorator模式应用的要点在于解决“主体类在多个方向上的扩展功能”--是为“装饰”的含义。
.NET FCL的输入输出类的整体设计就是一个Decorayor模. 先看一下下面的UML图.

下面是程序源码:
ISimpleWriter.cs
1
namespace Filters
2
{
3
/// <summary>
4
/// This interface defines the methods that Oozinoz filters must support.
5
/// </summary>
6
public interface ISimpleWriter
7
{
8
void Write(char c);
9
void Write(string s);
10
void WriteLine();
11
void Close();
12
}
13
}
14
OozinozFilter.cs
2

3

4

5

6

7

8

9

10

11

12

13

14

1
using System;
2
namespace Filters
3
{
4
5
public abstract class OozinozFilter : ISimpleWriter
6
{
7
protected ISimpleWriter _writer;
8
9
10
public OozinozFilter(ISimpleWriter writer)
11
{
12
_writer = writer;
13
}
14
15
public abstract void Write(char c);
16
17
18
public virtual void Write(string s)
19
{
20
foreach(char c in s.ToCharArray())
21
{
22
Write(c);
23
}
24
}
25
26
public virtual void WriteLine()
27
{
28
_writer.WriteLine();
29
}
30
31
public virtual void Close()
32
{
33
_writer.Close();
34
}
35
}
36
}
37
SimpleStreamWriter.cs
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

1
using System.IO;
2
namespace Filters
3
{
4
5
public class SimpleStreamWriter : StreamWriter, ISimpleWriter
6
{
7
8
public SimpleStreamWriter(Stream s) : base (s)
9
{
10
}
11
12
public SimpleStreamWriter(string path) : base (path)
13
{
14
}
15
}
16
}
17
TitleCaseFilter.cs
2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

1
using System;
2
namespace Filters
3
{
4
5
public class TitleCaseFilter : OozinozFilter
6
{
7
protected bool inWhite = true;
8
9
public TitleCaseFilter(ISimpleWriter writer) : base (writer)
10
{
11
}
12
13
14
public override void Write(char c)
15
{
16
_writer.Write(inWhite
17
? Char.ToUpper(c)
18
: Char.ToLower(c));
19
inWhite = Char.IsWhiteSpace(c) || c == '\"';
20
}
21
22
public override void WriteLine()
23
{
24
base.WriteLine();
25
inWhite = true;
26
}
27
}
28
}
29
WrapFilter.cs
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

1
using System;
2
using System.Text;
3
namespace Filters
4
{
5
6
public class WrapFilter : OozinozFilter
7
{
8
protected int _width;
9
protected StringBuilder lineBuf = new StringBuilder();
10
protected StringBuilder wordBuf = new StringBuilder();
11
protected bool _center = false;
12
protected bool _inWhite = false;
13
protected bool _needBlank = false;
14
15
public WrapFilter(ISimpleWriter writer, int width) : base (writer)
16
{
17
this._width = width;
18
}
19
20
public bool Center
21
{
22
get
23
{
24
return _center;
25
}
26
set
27
{
28
_center = value;
29
}
30
}
31
32
public override void Close()
33
{
34
Flush();
35
base.Close();
36
}
37
38
public void Flush()
39
{
40
if (wordBuf.Length > 0)
41
{
42
PostWord();
43
}
44
if (lineBuf.Length > 0)
45
{
46
PostLine();
47
}
48
}
49
50
protected void PostLine()
51
{
52
if (Center)
53
{
54
for (int i = 0; i < (_width - lineBuf.Length) / 2; i++)
55
{
56
_writer.Write(' ');
57
}
58
}
59
_writer.Write(lineBuf.ToString());
60
_writer.WriteLine();
61
}
62
63
protected void PostWord()
64
{
65
if (lineBuf.Length + 1 + wordBuf.Length > _width && (lineBuf.Length > 0))
66
{
67
PostLine();
68
lineBuf = wordBuf;
69
wordBuf = new StringBuilder();
70
}
71
else
72
{
73
if (_needBlank)
74
{
75
lineBuf.Append(" ");
76
}
77
lineBuf.Append(wordBuf);
78
_needBlank = true;
79
wordBuf = new StringBuilder();
80
}
81
}
82
83
public override void Write(char c)
84
{
85
if (Char.IsWhiteSpace(c))
86
{
87
if (!_inWhite)
88
{
89
PostWord();
90
}
91
_inWhite = true;
92
}
93
else
94
{
95
wordBuf.Append(c);
96
_inWhite = false;
97
}
98
}
99
}
100
}
101

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

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101
