装饰器模式(Decorator Pattern)
允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
通过采用组合、而非继承的手法,Decorator模式实现了在运行时动态地扩展对象功能的能力,而且可以
根据需要扩展多个功能。避免了单独使用继承带来的“灵活性差"和"多子类衍生问题"。
优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能
缺点:多层装饰比较复杂
使用场景: 1、扩展一个类的功能。 2、动态增加功能,动态撤销 例如游戏装备,以及各层vip,商场的多重优惠等等
应用实例:不论一幅画有没有画框都可以挂在墙上,但是通常都是有画框的,并且实际上是画框被挂在墙上。在挂在墙上之前,画可以被蒙上玻璃,装到框子里;这时画、玻璃和画框形成了一个物体
装饰器模式主要组成部分:
Component:定义一个对象接口,可以给这些对象动态地添加职责
ConcreteComponent:定义一个对象,可以给这个对象添加一些职责
Decorator:维持一个指向Component的指针,并定义一个与Component接口一致的接口
ConcreteDecorator:负责向ConcreteComponent添加功能
假如我们需要为游戏中开发一种坦克,除了各种不同型号的坦克外,我们还希望在不同场合中为其增加以下一种或多种功能;比如红外线夜视功能,比如水陆两栖功能,比如卫星定位功能等等
按类继承的作法如下:
1 //抽象坦克
2 public abstract class Tank
3 {
4 public abstract void Shot();
5 public abstract void Run();
6 }
View Code
各种型号:
1 //T50型号
2 public class T50:Tank
3 {
4 public override void Shot()
5 {
6 Console.WriteLine("T50坦克平均每秒射击5发子弹");
7 }
8 public override void Run()
9 {
10 Console.WriteLine("T50坦克平均每时运行30公里");
11 }
12 }
View Code
1 //T75型号
2 public class T75 : Tank
3 {
4 public override void Shot()
5 {
6 Console.WriteLine("T75坦克平均每秒射击10发子弹");
7 }
8 public override void Run()
9 {
10 Console.WriteLine("T75坦克平均每时运行35公里");
11 }
12 }
View Code
1 //T90型号
2 public class T90 :Tank
3 {
4 public override void Shot()
5 {
6 Console.WriteLine("T90坦克平均每秒射击10发子弹");
7 }
8 public override void Run()
9 {
10 Console.WriteLine("T90坦克平均每时运行40公里");
11 }
12 }
View Code
各种不同功能的组合:比如IA具有红外功能接口、IB具有水陆两栖功能接口、IC具有卫星定位功能接口。
1 //T50坦克各种功能的组合
2 public class T50A:T50,IA
3 {
4 //具有红外功能
5 }
6 public class T50B:T50,IB
7 {
8 //具有水陆两栖功能
9 }
10 public class T50C:T50,IC
11 {
12
13 }
14 public class T50AB:T50,IA,IB
15 {}
16 public class T50AC:T50,IA,IC
17 {}
18 public class T50BC:T50,IB,IC
19 {}
20 public class T50ABC:T50,IA,IB,IC
21 {}
View Code
1 //T75各种不同型号坦克各种功能的组合
2 public class T75A:T75,IA
3 {
4 //具有红外功能
5 }
6 public class T75B:T75,IB
7 {
8 //具有水陆两栖功能
9 }
10 public class T75C:T75,IC
11 {
12 //具有卫星定位功能
13 }
14 public class T75AB:T75,IA,IB
15 {
16 //具有红外、水陆两栖功能
17 }
18 public class T75AC:T75,IA,IC
19 {
20 //具有红外、卫星定位功能
21 }
22 public class T75BC:T75,IB,IC
23 {
24 //具有水陆两栖、卫星定位功能
25 }
26 public class T75ABC:T75,IA,IB,IC
27 {
28 //具有红外、水陆两栖、卫星定位功能
29 }
View Code
1 //T90各种不同型号坦克各种功能的组合
2 public class T90A:T90,IA
3 {
4 //具有红外功能
5 }
6 public class T90B:T90,IB
7 {
8 //具有水陆两栖功能
9 }
10 public class T90C:T90,IC
11 {
12 //具有卫星定位功能
13 }
14 public class T90AB:T90,IA,IB
15 {
16 //具有红外、水陆两栖功能
17 }
18 public class T90AC:T90,IA,IC
19 {
20 //具有红外、卫星定位功能
21 }
22 public class T90BC:T90,IB,IC
23 {
24 //具有水陆两栖、卫星定位功能
25 }
26 public class T90ABC:T90,IA,IB,IC
27 {
28 //具有红外、水陆两栖、卫星定位功能
29 }
View Code
由此可见,如果用类继承实现,子类会爆炸式地增长
装饰器模式实现代码:
1 namespace Decorator
2 {
3 public abstract class Tank
4 {
5 public abstract void Shot();
6 public abstract void Run();
7 }
8 }
View Code
1 public class T50:Tank
2 {
3 public override void Shot()
4 {
5 Console.WriteLine("T50坦克平均每秒射击5发子弹");
6 }
7 public override void Run()
8 {
9 Console.WriteLine("T50坦克平均每时运行30公里");
10 }
11 }
View Code
1 public class T75 : Tank
2 {
3 public override void Shot()
4 {
5 Console.WriteLine("T75坦克平均每秒射击10发子弹");
6 }
7 public override void Run()
8 {
9 Console.WriteLine("T75坦克平均每时运行35公里");
10 }
11 }
View Code
1 public class T90 :Tank
2 {
3 public override void Shot()
4 {
5 Console.WriteLine("T90坦克平均每秒射击10发子弹");
6 }
7 public override void Run()
8 {
9 Console.WriteLine("T90坦克平均每时运行40公里");
10 }
11 }
View Code
1 public abstract class Decorator :Tank //Do As 接口继承 非实现继承
2 {
3 private Tank tank; //Has a 对象组合
4 public Decorator(Tank tank)
5 {
6 this.tank = tank;
7 }
8 public override void Shot()
9 {
10 tank.Shot();
11 }
12 public override void Run()
13 {
14 tank.Run();
15 }
16 }
View Code
1 public class DecoratorA :Decorator
2 {
3 public DecoratorA(Tank tank) : base(tank)
4 {
5 }
6 public override void Shot()
7 {
8 //Do some extension //功能扩展 且有红外功能
9 base.Shot();
10 }
11 public override void Run()
12 {
13
14 base.Run();
15 }
16 }
View Code
1 public class DecoratorB :Decorator
2 {
3 public DecoratorB(Tank tank) : base(tank)
4 {
5 }
6 public override void Shot()
7 {
8 //Do some extension //功能扩展 且有水陆两栖功能
9 base.Shot();
10 }
11 public override void Run()
12 {
13 base.Run();
14 }
15 }
View Code
1 public class DecoratorC :Decorator
2 {
3 public DecoratorC(Tank tank) : base(tank)
4 {
5 }
6 public override void Shot()
7 {
8 //Do some extension //功能扩展 且有卫星定位功能
9 base.Shot();
10 }
11 public override void Run()
12 {
13
14 base.Run();
15 }
16
17 }
View Code
前端调用:
1 static void Main(string[] args)
2 {
3 Tank tank = new T50();
4 DecoratorA da = new DecoratorA(tank); //且有红外功能
5 DecoratorB db = new DecoratorB(da); //且有红外和水陆两栖功能
6 DecoratorC dc = new DecoratorC(db); //且有红外、水陆两栖、卫星定们三种功能
7 dc.Shot();
8 dc.Run();
9 }
View Code
Decorator在.NET(Stream)中的应用:
BufferedStream和CryptoStream其实就是两个包装类,这里的Decorator模式省略了抽象装饰角色(Decorator),示例代码如下:
1 public static void Main(string[] args)
2 {
3 MemoryStream ms =
4 new MemoryStream(new byte[] { 100,456,864,222,567});
5 //扩展了缓冲的功能
6 BufferedStream buff = new BufferedStream(ms);
7
8 //扩展了缓冲,加密的功能
9 CryptoStream crypto = new CryptoStream(buff);
10 }
View Code
1 public sealed class BufferedStream : Stream
2 {
3 // Methods
4 private BufferedStream();
5 public BufferedStream(Stream stream);
6 public BufferedStream(Stream stream, int bufferSize);
7 // Fields
8 private int _bufferSize;
9 private Stream _s;
10 }
View Code
通过反编译,可以看到BufferedStream类的代码(只列出部分),它是继承于Stream类
本文参考文档:
https://www.runoob.com/design-pattern/decorator-pattern.html
作者:德乌姆列特
本博客所有文章仅用于学习、研究和交流目的,欢迎非商业性质转载。
博主的文章没有高度、深度和广度,只是凑字数。由于博主的水平不高,不足和错误之处在所难免,希望大家能够批评指出。
博主是利用读书、参考、引用、抄袭、复制和粘贴等多种方式打造成自己的文章,请原谅博主成为一个无耻的文档搬运工!