装饰器模式(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 }
各种型号:
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 }
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 }
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 }
各种不同功能的组合:比如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 {}
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 }
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 }
由此可见,如果用类继承实现,子类会爆炸式地增长
装饰器模式实现代码:
1 namespace Decorator 2 { 3 public abstract class Tank 4 { 5 public abstract void Shot(); 6 public abstract void Run(); 7 } 8 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
前端调用:
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 }
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 }
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 }
通过反编译,可以看到BufferedStream类的代码(只列出部分),它是继承于Stream类
本文参考文档:
https://www.cnblogs.com/abcdwxc/archive/2007/09/06/884495.html
https://www.runoob.com/design-pattern/decorator-pattern.html
https://www.cnblogs.com/banluduxing/p/9152453.html
原文地址:https://www.cnblogs.com/Dewumu/p/11447379.html