• 23种设计模式之装饰器模式(Decorator Pattern)


     装饰器模式(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.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

  • 相关阅读:
    opencv MAT数据操作
    浅谈模式识别中的特征提取
    设置Mysql的连接超时参数
    win7下怎样设置putty免用户名密码登陆
    正则表达式简明参考
    利用 canvas 破解 某拖动验证码
    wamp环境中mysql更改root密码
    Python读写文件
    Python 字符串操作(string替换、删除、截取、复制、连接、比较、查找、包含、大小写转换、分割等)
    如何改变placeholder的颜色
  • 原文地址:https://www.cnblogs.com/Dewumu/p/11447379.html
Copyright © 2020-2023  润新知