分享

【C#设计模式-装饰者模式】

 鸿枫nh 2017-02-21

一.装饰者模式的定义:

装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

结构:

(1)抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。
(2)具体构件(Concrete Component)角色:定义一个将要接收附加责任的类。 
(3)装饰(Decorator)角色:持有一个构件(Component)对象的实例,并实现一个与抽象构件接口一致的接口。
(4)具体装饰(Concrete Decorator)角色:负责给构件对象添加上附加的责任。              

二.装饰者模式的实现:

这里应用显示生活中的例子,我们买了一部新手机,慢慢的给这部手机添加新的装饰,比如说贴膜,添加挂件.....

首先抽象出手机类,作为装饰者模式中的抽象组件:

[csharp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. /// <summary>  
  2. /// 手机抽象类,即抽象者模式中的抽象组件类  
  3. /// </summary>  
  4. public abstract class Phone  
  5. {  
  6.     /// <summary>  
  7.     /// 打印方法  
  8.     /// </summary>  
  9.     public abstract void Print();  
  10. }  

假如现在我们买了一部苹果手机,现在继承自抽象类,实现具体组件类。

[csharp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. /// <summary>  
  2. /// 苹果手机,即装饰着模式中的具体组件类  
  3. /// </summary>  
  4. public class ApplePhone:Phone  
  5. {  
  6.     /// <summary>  
  7.     /// 重写基类的方法  
  8.     /// </summary>  
  9.     public override void Print()  
  10.     {  
  11.         Console.WriteLine("我有一部苹果手机");  
  12.     }  
  13. }  

现在我想给这个手机添加新的装饰:我们先抽象出装饰类:

[csharp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. /// <summary>  
  2. /// 装饰抽象类,让装饰完全取代抽象组件,所以必须继承Phone  
  3. /// </summary>  
  4. public abstract class Decorator:Phone  
  5. {  
  6.     private Phone p ;    //该装饰对象装饰到的Phone组件实体对象  
  7.       
  8.     public Decorator(Phone p)  
  9.     {  
  10.         this.p = p;  
  11.     }  
  12.   
  13.     public override void Print()  
  14.     {  
  15.         if (this.p != null)  
  16.         {  
  17.             p.Print();  
  18.         }  
  19.     }  
  20. }  

具体装饰对象,继承装饰抽象类:这里具体贴膜装饰,和挂件装饰:

[csharp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. /// <summary>  
  2. /// 贴膜,具体装饰者  
  3. /// </summary>  
  4. public class Sticker:Decorator  
  5. {  
  6.     public Sticker(Phone p) : base(p) { }  
  7.   
  8.     public override void Print()  
  9.     {  
  10.         base.Print();  
  11.         //添加行为  
  12.         AddSticker();  
  13.     }  
  14.   
  15.     /// <summary>  
  16.     /// 新的行为方法  
  17.     /// </summary>  
  18.     public void AddSticker()  
  19.     {  
  20.         Console.WriteLine("现在苹果手机有贴膜了");  
  21.     }  
  22. }  
[csharp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. /// <summary>  
  2. /// 手机挂件,即具体装饰者  
  3. /// </summary>  
  4. public class Accessories:Decorator  
  5. {  
  6.     public Accessories(Phone p) : base(p) { }  
  7.   
  8.     public override void Print()  
  9.     {  
  10.         base.Print();  
  11.   
  12.         // 添加新的行为  
  13.         AddAccessories();  
  14.     }  
  15.   
  16.     /// <summary>  
  17.     /// 新的行为方法  
  18.     /// </summary>  
  19.     public void AddAccessories()  
  20.     {  
  21.         Console.WriteLine("现在苹果手机有漂亮的挂件了");  
  22.     }  
  23. }  

使用如下:

[csharp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. /// <summary>  
  2. /// 设计模式-装饰者模式  
  3. /// </summary>  
  4. class Program  
  5. {  
  6.     static void Main(string[] args)  
  7.     {  
  8.         Phone ap = new ApplePhone(); //新买了个苹果手机  
  9.         Decorator aps = new Sticker(ap); //准备贴膜组件  
  10.         aps.Print();  
  11.   
  12.         Decorator apa = new Accessories(ap); //过了几天新增了挂件组件  
  13.         apa.Print();  
  14.   
  15.         Sticker s = new Sticker(ap);       //准备贴膜组件  
  16.         Accessories a = new Accessories(s);//同时准备挂件  
  17.         a.Print();   
  18.     }  
  19. }  

类图关系如下:

        (1)抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。>这里就是Phone接口
  (2)具体构件(Concrete Component)角色:定义一个将要接收附加责任的类。                   >这里指的ApplePhone
  (3)装饰(Decorator)角色:持有一个构件(Component)对象的实例,并实现一个与抽象构件接口一致的接口。>指的Decorator
  (4)具体装饰(Concrete Decorator)角色:负责给构件对象添加上附加的责任。                   >指的是Accessories和Sticker

优点:

1. Decorator模式与继承关系的目的都是要扩展对象的功能,但是Decorator可以提供比继承更多的灵活性。
2. 通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。

缺点:

1. 这种比继承更加灵活机动的特性,也同时意味着更加多的复杂性。
2. 装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。
3. 装饰模式是针对抽象组件(Component)类型编程。但是,如果你要针对具体组件编程时,就应该重新思考你的应用架构,以及装饰者是否合适。当然也可以改变Component接口,增加新的公开的行为,实现“半透明”的装饰者模式。在实际项目中要做出最佳选择。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多