zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    Hibernate save, saveOrUpdate, persist, merge, update 区别
    Eclipse下maven使用嵌入式(Embedded)Neo4j创建Hello World项目
    Neo4j批量插入(Batch Insertion)
    嵌入式(Embedded)Neo4j数据库访问方法
    Neo4j 查询已经创建的索引与约束
    Neo4j 两种索引Legacy Index与Schema Index区别
    spring data jpa hibernate jpa 三者之间的关系
    maven web project打包为war包,目录结构的变化
    创建一个maven web project
    Linux下部署solrCloud
  • 原文地址:https://www.cnblogs.com/Dewumu/p/11447379.html
Copyright © 2011-2022 走看看