NET设计模式之一:装饰模式(Decorator Pattern)
最近看了blog牛人张逸写的设计之道,在文中设计模式的例子中运用了Decorator模式.怎么看怎么不理解(忘记说了,本人智商Te低),于是一个晚上没有睡着觉,在网上搜索Decorator的讲解.看了Terrylee的设计模式.看了lovecherry的无废话设计模式,也拜读了wxj1020<head First>设计模式系列(在此特别感谢各位,特献上最崇高的敬意).经过720个分钟的努力终于对decorator模式有一点点理解,为了加深对她的记忆.特此记录下来(也是怕忘记了.智商低的人忘记的特快).
Decorator模式
1:意图:动态的为一些对象添加一些职责(何为动态?晕死,我的理解就是,不通过继承而增加对象功能!).
2:结构图(不是俺画的)

3 实例(别讲那些高深的理论的东西,实践出真知,抓紧看一下吧)
项目背景:一个图书馆有两种刊物可以外借书籍(Books)和音像(Videos),开始都免费.看下类图吧

都是很简单的关系.继承.代码也很简单
LibraryItem.cs
.完了.本来想通过自家继承的子类来实现,发现这样要增加3个子类,如果要是有其他的变化,子类又要多了.咋办?呵呵.聪明的你想到了.Decorator帮你实现(现代人就是轻松,老一辈啥都给你准备好了).看一下Decorator类图吧

看看代码吧
BooksDecorator.cs
VideosDecorator.cs

Decorator模式
1:意图:动态的为一些对象添加一些职责(何为动态?晕死,我的理解就是,不通过继承而增加对象功能!).
2:结构图(不是俺画的)

3 实例(别讲那些高深的理论的东西,实践出真知,抓紧看一下吧)
项目背景:一个图书馆有两种刊物可以外借书籍(Books)和音像(Videos),开始都免费.看下类图吧

都是很简单的关系.继承.代码也很简单
LibraryItem.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
5
namespace Decorator
6
{
7
public abstract class LibraryItem
8
{
9
public abstract void Free();
10
11
// void Charge();
12
}
13
}
14
Books.cs
using System;2
using System.Collections.Generic;3
using System.Text;4

5
namespace Decorator6
{7
public abstract class LibraryItem8
{9
public abstract void Free();10
11
// void Charge();12
}13
}14

1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
5
namespace Decorator
6
{
7
public class Books : LibraryItem
8
{
9
public override void Free()
10
{
12
Console.WriteLine("借书籍准则");
13
}
14
}
15
}
16
Vedios.cs
using System;2
using System.Collections.Generic;3
using System.Text;4

5
namespace Decorator6
{7
public class Books : LibraryItem8
{ 9
public override void Free()10
{ 12
Console.WriteLine("借书籍准则");13
}14
}15
}16

1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
5
namespace Decorator
6
{
7
public class Vedios:LibraryItem
8
{
9
public override void Free()
10
{
11
Console.WriteLine("借录像准则");
12
}
13
}
14
}
15
实现以上的功能.我们的设计还可以胜任.突然某天,图书馆老板变成"黄世仁"了.晕死.看书要书费.不过为了能顺利的进行不收费到收费的过度,他制定了详细的计划女生借书要钱,男生借Videos要钱.说不定改天对男生女生都收钱.
using System;2
using System.Collections.Generic;3
using System.Text;4

5
namespace Decorator6
{7
public class Vedios:LibraryItem8
{ 9
public override void Free()10
{ 11
Console.WriteLine("借录像准则"); 12
} 13
}14
}15

.完了.本来想通过自家继承的子类来实现,发现这样要增加3个子类,如果要是有其他的变化,子类又要多了.咋办?呵呵.聪明的你想到了.Decorator帮你实现(现代人就是轻松,老一辈啥都给你准备好了).看一下Decorator类图吧

看看代码吧
BooksDecorator.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
5
namespace Decorator
6
{
7
public class BooksDecorator:LibraryDecorator
8
{
9
public BooksDecorator(LibraryItem liraryItem)
10
: base(liraryItem)
11
{ }
12
public override void Free()
13
{
14
base.Free();
15
//数据对女孩收费
16
ChargeForGirls();
17
18
}
19
public void ChargeForGirls()
20
{
21
Console.WriteLine("Books cost 100$ for Girls");
22
}
23
}
24
}
25
using System;2
using System.Collections.Generic;3
using System.Text;4

5
namespace Decorator6
{7
public class BooksDecorator:LibraryDecorator8
{9
public BooksDecorator(LibraryItem liraryItem)10
: base(liraryItem)11
{ }12
public override void Free()13
{14
base.Free();15
//数据对女孩收费16
ChargeForGirls();17
18
}19
public void ChargeForGirls()20
{21
Console.WriteLine("Books cost 100$ for Girls");22
}23
}24
}25

VideosDecorator.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
5
namespace Decorator
6
{
7
public class VideosDecorator:LibraryDecorator
8
{
9
public VideosDecorator(LibraryItem libraryItem)
10
: base(libraryItem)
11
{ }
12
public override void Free()
13
{
14
base.Free();
15
//videos 对男生收费
16
ChargeForBoys();
17
}
18
public void ChargeForBoys()
19
{
20
Console.WriteLine("Videos cost 150$ for boys !");
21
}
22
}
23
}
24
最后看下条用的程序
using System;2
using System.Collections.Generic;3
using System.Text;4

5
namespace Decorator6
{7
public class VideosDecorator:LibraryDecorator8
{9
public VideosDecorator(LibraryItem libraryItem)10
: base(libraryItem)11
{ }12
public override void Free()13
{14
base.Free();15
//videos 对男生收费16
ChargeForBoys(); 17
}18
public void ChargeForBoys()19
{20
Console.WriteLine("Videos cost 150$ for boys !");21
}22
}23
}24

1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
5
namespace Decorator
6
{
7
class Program
8
{
9
static void Main(string[] args)
10
{
11
//
12
LibraryItem libItem = null;
13
libItem = new Books();
14
15
//decorator效果
16
LibraryDecorator libDecorator = null;
17
//增加女孩借书免费的功能
18
Console.WriteLine("增加女生书籍收费的功能");
19
libDecorator = new BooksDecorator(libItem);
20
libDecorator.Free();
21
Console.WriteLine();
22
23
libItem = new Vedios();
24
25
//增加男生借Videos免费的功能
26
Console.WriteLine("增加男生Videos收费的功能");
27
libDecorator = new VideosDecorator(libItem);
28
libDecorator.Free();
29
Console.WriteLine();
30
31
//对于所有男生女生,书籍和videos都免费
32
Console.WriteLine("增加男生,女生对书籍和videos都收费");
33
libDecorator = new BooksDecorator(libDecorator);
34
libDecorator.Free();
35
36
37
}
38
}
39
}
40
看看运行结果
using System;2
using System.Collections.Generic;3
using System.Text;4

5
namespace Decorator6
{7
class Program8
{9
static void Main(string[] args)10
{11
//12
LibraryItem libItem = null;13
libItem = new Books();14
15
//decorator效果16
LibraryDecorator libDecorator = null;17
//增加女孩借书免费的功能18
Console.WriteLine("增加女生书籍收费的功能");19
libDecorator = new BooksDecorator(libItem);20
libDecorator.Free();21
Console.WriteLine();22

23
libItem = new Vedios();24
25
//增加男生借Videos免费的功能26
Console.WriteLine("增加男生Videos收费的功能");27
libDecorator = new VideosDecorator(libItem);28
libDecorator.Free();29
Console.WriteLine();30

31
//对于所有男生女生,书籍和videos都免费32
Console.WriteLine("增加男生,女生对书籍和videos都收费");33
libDecorator = new BooksDecorator(libDecorator);34
libDecorator.Free();35

36

37
}38
}39
}40

适用性
在以下情况下应当使用装饰模式:
1.需要扩展一个类的功能,或给一个类增加附加责任。
2.需要动态地给一个对象增加功能,这些功能可以再动态地撤销。
3.需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变得不现实。
总结
Decorator模式采用对象组合而非继承的手法,实现了在运行时动态的扩展对象功能的能力,而且可以根据需要扩展多个功能,避免了单独使用继承带来的“灵活性差”和“多子类衍生问题”。同时它很好地符合面向对象设计原则中“优先使用对象组合而非继承”和“开放-封闭”原则。
参考资料
最近看了blog牛人张逸写的设计之道,在文中设计模式的例子中运用了Decorator模式.怎么看怎么不理解(忘记说了,本人智商50),于是一个晚上没有睡着觉,在网上搜索Decorator的讲解.看了Terrylee的设计模式.看了lovecherry的无废话设计模式,也拜读了wxj1020设计模式系列(在此特别感谢各位,特献上最崇高的敬意).经过720个分钟的努力终于对decorator模式有一点点理解(对于一个智商50的人来说,不容易,应该得到鼓励),为了加深对她的记忆.特此记录下来(也是怕忘记了,俺忘记的特快).


浙公网安备 33010602011771号