设计模式DecoratorStructure标签03标签04标签05
C#10:(结构型模式) Decorator 装饰模式.pdf
说明:
- 装饰模式
- 结构型模式
视频
子类复子类,子类何其多
假如我们需要为游戏中开发一种坦克,除了各种不同型号的坦克外,我们还希望在不同场合中为其增加以下一种或多种功能;比如红外线夜视功能,比如水陆两栖功能,比如卫星定位功能等等。<br />按类继承的作法如下:
//抽象坦克public abstract class Tank3{public abstract void Shot();public abstract void Run();}
各种型号:
//T50型号public class T50:Tank{public override void Shot(){Console.WriteLine("T50坦克平均每秒射击5发子弹");}public override void Run(){Console.WriteLine("T50坦克平均每时运行30公里");}}
//T75型号public class T75 : Tank{public override void Shot(){Console.WriteLine("T75坦克平均每秒射击10发子弹");}public override void Run(){Console.WriteLine("T75坦克平均每时运行35公里");}}
//T90型号public class T90 :Tank{public override void Shot(){Console.WriteLine("T90坦克平均每秒射击10发子弹");}public override void Run(){Console.WriteLine("T90坦克平均每时运行40公里");}}
各种不同功能的组合:比如IA具有红外功能接口、IB具有水陆两栖功能接口、IC具有卫星定位功能接口。
//T50坦克各种功能的组合public class T50A:T50,IA{//具有红外功能}public class T50B:T50,IB{//具有水陆两栖功能}public class T50C:T50,IC1{}public class T50AB:T50,IA,IB{}public class T50AC:T50,IA,IC{}public class T50BC:T50,IB,IC{}public class T50ABC:T50,IA,IB,IC{}
//T75各种不同型号坦克各种功能的组合public class T75A:T75,IA{//具有红外功能}public class T75B:T75,IB{//具有水陆两栖功能}public class T75C:T75,IC{//具有卫星定位功能}public class T75AB:T75,IA,IB{//具有红外、水陆两栖功能}public class T75AC:T75,IA,IC{//具有红外、卫星定位功能}public class T75BC:T75,IB,IC{//具有水陆两栖、卫星定位功能}public class T75ABC:T75,IA,IB,IC{//具有红外、水陆两栖、卫星定位功能}
//T90各种不同型号坦克各种功能的组合public class T90A:T90,IA{//具有红外功能}public class T90B:T90,IB{//具有水陆两栖功能}public class T90C:T90,IC{//具有卫星定位功能}public class T90AB:T90,IA,IB{//具有红外、水陆两栖功能}public class T90AC:T90,IA,IC{//具有红外、卫星定位功能}public class T90BC:T90,IB,IC{//具有水陆两栖、卫星定位功能}public class T90ABC:T90,IA,IB,IC{//具有红外、水陆两栖、卫星定位功能}
动机(Motivate):
上述描述的问题根源在于我们“过度地使用了继承来扩展对象的功能”,由于继承为类型引入的静态物质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能组合)会导致更多子类的膨胀(多继承)。<br /> 如何使“对象功能的扩展”能够根据需要来动态地实现?同时避免“扩展功能的增多”带来的子类膨胀问题?从而使得任何“功能扩展变化”所导致的影响将为最低?
意图(Intent):
动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。<br /> ------《设计模式》GOF
结构图(Struct):

生活中的例子:

适用性:
需要扩展一个类的功能,或给一个类增加附加责任。需要动态地给一个对象增加功能,这些功能可以再动态地撤销。需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变得不现实。
实现代码:
namespace Decorator{public abstract class Tank{public abstract void Shot();public abstract void Run();}}
namespace Decorator{public class T50:Tank{public override void Shot(){Console.WriteLine("T50坦克平均每秒射击5发子弹");}public override void Run(){Console.WriteLine("T50坦克平均每时运行30公里");}}}
namespace Decorator{public class T75 : Tank{public override void Shot(){Console.WriteLine("T75坦克平均每秒射击10发子弹");}public override void Run(){Console.WriteLine("T75坦克平均每时运行35公里");}}}
namespace Decorator{public class T90 :Tank{public override void Shot(){Console.WriteLine("T90坦克平均每秒射击10发子弹");}public override void Run(){Console.WriteLine("T90坦克平均每时运行40公里");}}}
namespace Decorator{public abstract class Decorator :Tank //Do As 接口继承 非实现继承{private Tank tank; //Has a 对象组合public Decorator(Tank tank){this.tank = tank;}public override void Shot(){tank.Shot();}public override void Run(){tank.Run();}}}
namespace Decorator{public class DecoratorB :Decorator{public DecoratorB(Tank tank) : base(tank){}public override void Shot(){//Do some extension //功能扩展 且有水陆两栖功能base.Shot();}public override void Run(){base.Run();}}}
namespace Decorator{public class DecoratorA :Decorator{public DecoratorA(Tank tank) : base(tank){}public override void Shot(){//Do some extension //功能扩展 且有红外功能base.Shot();}public override void Run(){base.Run();}}}
namespace Decorator{public class DecoratorC :Decorator{public DecoratorC(Tank tank) : base(tank){}public override void Shot(){//Do some extension //功能扩展 且有卫星定位功能base.Shot();}public override void Run(){base.Run();}}}
class Program{static void Main(string[] args){Tank tank = new T50();DecoratorA da = new DecoratorA(tank); //且有红外功能DecoratorB db = new DecoratorB(da); //且有红外和水陆两栖功能DecoratorC dc = new DecoratorC(db); //且有红外、水陆两栖、卫星定们三种功能dc.Shot();dc.Run();}}
Decorator模式的几个要点:
通过采用组合、而非继承的手法,Decorator模式实现了在运行时动态地扩展对象功能的能力,而且可以<br />根据需要扩展多个功能。避免了单独使用继承带来的“灵活性差"和"多子类衍生问题"。<br /> Component类在Decorator模式中充当抽象接口的角色,不应该去实现具体的行为。而且Decorator类对于Component类应该透明---换言之Component类无需知道Decorator类,Decorator类是从外部来扩展Component类的功能。<br /> Decorator类在接口上表现为is-a Component的继承关系,即Decorator类继承了Component类所且有的接口。但在实现上又表现has a Component的组合关系,即Decorator类又使用了另外一个Component类。我们可以使用一个或者多个Decorator对象来“装饰”一个Component对象,且装饰后的对象仍然是一个Component对象。<br /> Decorator模式并非解决”多子类衍生的多继承“问题,Decorator模式应用的要点在于解决“主体<br />类在多个方向上的扩展功能”------是为“装饰”的含义。
Decorator在.NET(Stream)中的应用:

可以看到, BufferedStream和CryptoStream其实就是两个包装类,这里的Decorator模式省略了抽象装饰角色(Decorator),示例代码如下:
class Program{public static void Main(string[] args){MemoryStream ms =new MemoryStream(new byte[] { 100,456,864,222,567});//扩展了缓冲的功能BufferedStream buff = new BufferedStream(ms);//扩展了缓冲,加密的功能CryptoStream crypto = new CryptoStream(buff);}}
通过反编译,可以看到BufferedStream类的代码(只列出部分),它是继承于Stream类:
public sealed class BufferedStream : Stream{// Methodsprivate BufferedStream();public BufferedStream(Stream stream);public BufferedStream(Stream stream, int bufferSize);// Fieldsprivate int _bufferSize;private Stream _s;}
- 本文作者:GeekPower - Felix Sun
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!
