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      }

各种型号:

 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

时间: 2024-12-29 07:01:55

23种设计模式之装饰器模式(Decorator Pattern)的相关文章

23种设计模式之装饰器模式

装饰器模式主要有以下元素: 1.Component为统一接口,也是装饰类和被装饰类的基本类型.2.ConcreteComponent为具体实现类,也是被装饰类,他本身是个具有一些功能的完整的类.3.Decorator是装饰类,实现了Component接口的同时还在内部维护了一个ConcreteComponent的实例,并可以通过构造函数初始化.而Decorator本身,通常采用默认实现,他的存在仅仅是一个声明:我要生产出一些用于装饰的子类了.而其子类才是赋有具体装饰效果的装饰产品类.4.Conc

设计模式(三)——装饰器模式(Decorator Pattern)

发现太过于刻意按照计划来写博客,有点不实际,刚好最近在一个网课上复习AOP的知识,讲到了装饰器模式和代理模式,顺便复习总结一下. 首先了解一下装饰器模式,从名字里面可以看出来,装饰器模式就类似于房子装潢吧,比如刚买的毛坯房,只有一个没有门,直接就可以进去. 首先设计一个房子类Room,实现一个进入方法Access /// <summary> /// 抽象接口 用来进行约束 /// </summary> public interface IAccess { void Access()

用最简单的例子理解装饰器模式(Decorator Pattern)

假设有一个公司要做产品套餐,即把不同的产品组合在一起,不同的组合对应不同的价格.最终呈现出来的效果是:把产品组合的所有元素呈现出来,并显示该组合的价格. 每个产品都有名称和价格,首先设计一个关于产品的抽象基类. public abstract class ProductBase { public abstract string GetName(); public abstract double GetPrice(); } 所有的产品都必须继承这个基类,比如家居用品.电器产品等,把这些具体的产品提

php装饰器模式(decorator pattern)

十一点了. <?php /* The decorator pattern allows behavior to be added to an individual object instance, without affecting the behavior of other instances of the same class. We can define multiple decorators, where each adds new functionality. */ interface

设计模式之装饰器模式

一.百科 概述: 23种设计模式之一,英文叫Decorator Pattern,又叫装饰者模式.装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能.它是通过创建一个包装对象,也就是装饰来包裹真实的对象. 特点: (1) 装饰对象和真实对象有相同的接口.这样客户端对象就能以和真实对象相同的方式和装饰对象交互. (2) 装饰对象包含一个真实对象的引用(reference) (3) 装饰对象接受所有来自客户端的请求.它把这些请求转发给真实的对象. (4) 装饰对象可以在转发这些请

设计模式(八)装饰器模式Decorator(结构型)

设计模式(八)装饰器模式Decorator(结构型) 1. 概述 若你从事过面向对象开发,实现给一个类或对象增加行为,使用继承机制,这是所有面向对象语言的一个基本特性.如果已经存在的一个类缺少某些方法,或者须要给方法添加更多的功能(魅力),你也许会仅仅继承这个类来产生一个新类—这建立在额外的代码上. 通过继承一个现有类可以使得子类在拥有自身方法的同时还拥有父类的方法.但是这种方法是静态的,用户不能控制增加行为的方式和时机.如果  你希望改变一个已经初始化的对象的行为,你怎么办?或者,你希望继承许

说说设计模式~装饰器模式(Decorator)

装饰器模式,也叫又叫装饰者模式,顾名思义,将一个对象进行包裹,包装,让它变成一个比较满意的对象,这种模式在我们平时项目开发中,经常会用到,事实上,它是处理问题的一种技巧,也很好的扩展了程序,让程序代码不那么死板! 何时能用到它? 1. 需要扩展一个类的功能,或给一个类添加附加职责. 2. 需要动态的给一个对象添加功能,这些功能可以再动态的撤销. 3. 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实. 4. 当不能采用生成子类的方法进行扩充时. 其中我们认为第四种

Java经典23种设计模式之结构型模式(二)

接上篇,本文介绍结构型模式里的组合模式.装饰模式.外观模式. 一.组合模式(Composite) 组合模式:将对象组合成树形结构,表示"部分--整体"的层次结构.最终达到单个对象和组合对象的使用具有一致性.单看这句话貌似有点抽象,其实比较简单. 以李云龙的独立团为例,目的要统计赵嘉宇一战共歼灭敌人多少个.最高的级别是团,一个团有若干个营,一个营有若干个排,一个排有若干个战士.(为了简化问题,排下面就不设行政单位了).很自然的,李云龙给营长开会回去给老子统计.营长回去给各个排长开会,赶紧

java设计模式之 装饰器模式

适AT java设计模式之 装饰器模式 装饰器模式 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构. 这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,动态给一个对象添提供了额外的功能. 我们通过下面的实例来演示装饰器模式的用法.模拟一个人从想吃饭.找饭店.享受美食.结束吃饭的过程 代码展示: 首先创建一个被修饰的接口 Eat package deco