Decorator装饰(结构型模式)
动机:
如何使“对象功能的扩展”能够根据需要来动态地实现?同时避免“扩展功能的增多”带来的子类膨胀的问题?从而使得任何“功能扩展变化”所导致的影响降为最低?
意图:
动态地给一个对象增加一些额外的职责。就增加功能而言,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
如何使“对象功能的扩展”能够根据需要来动态地实现?同时避免“扩展功能的增多”带来的子类膨胀的问题?从而使得任何“功能扩展变化”所导致的影响降为最低?
意图:
动态地给一个对象增加一些额外的职责。就增加功能而言,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
1namespace 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.cs2{
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
1using System;
2namespace 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.cs2namespace 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
1using System.IO;
2namespace 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.cs2namespace 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
1using System;
2namespace 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.cs2namespace 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
1using System;
2using System.Text;
3namespace 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
2using System.Text;
3namespace 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