.NET简谈设计模式之(装饰者模式)

发表于:2011-9-14 09:42

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:王清培    来源:51Testing软件测试网采编

  装饰者模式其实有点难以理解,特别是对初学者来说可能有点晕,因为它的概念互相冲突,哪里互相冲突我们下面会讲解到。

  本人保持一贯的写作风格,重在入门。在本人的这篇文章中会用一个比较恰当的比喻来让我们对问题迎刃而解,例子虽然简单但是重点突出。

  在写这篇文章之前我在网上大概搜了一下关于“装饰者模式”的一些文章,但是讲解的效果都不太理想。要么就是找书搬过来的,要么就是对着书的例子从新创造一个。我看了大概三四篇这样子,不行看着头晕。文章的主人很想把问题的关键说清楚,但是很少能在原有代码的基础上画龙点睛,搞不好就是画蛇添足。如果没能清楚的介绍模式代码中的任何一脚,都有可能給看文章的初学者带来新的问题,没能够透彻的体现出文章的重点。下面我们从理清头绪开始。

  设计模式是用来解决某一个问题的一个方法,一个模式是对应着一个问题,比如观察者模式就是用来解决一对多的关系,这种关系是“牵一发而动全身”的作用。

  我们所看的设计模式书籍是一系列问题的集合,也是设计模式的集合。在我们还没有能力将他们融会贯通之前,先单独理解这些思想。当我们能驾驭这些设计模式之后,我们就能够设计出不错的系统架构。模式之间是相通的,“设计原则”是引导模式创新的根本。书上的模式多数都是用来考虑一些小例子而已,如果用在真正的项目中,就需要结合整个设计模式的运用了。所以当我们学习一些小的设计模式时,我们不牵扯到其他的多余东西,先理解我们当前模式的真正的思想是什么。

  装饰者模式定义:动态将职责附加到对象上,若要扩展功能,装饰者提供了比继承更具弹性的代替方案;

  这是装饰者模式比较官方的定义,这句话我们基本上都能理解其含义是什么。无非是动态的给要扩展的对象加上功能,不用继承而是用组合的方式。就是这句话给我们初学者带来了第一个问题,是用组合而不是用继承来扩展对象的功能。我们第一次接触装饰者模式的时候,就盯住了这句话,就是因为我们盯住了这句话,所以我们在下面的思考过程中总是带着这个理论,所以总是会理解不了。朋友先不要记这个理论,先抛开不要记任何理论模型,我会用一个比喻来逐渐的让你理解装饰者模式真正的含义是什么。

  请进入我的学习模式,在这里我打一个比喻;假如我家里现在要装修,要装修一个天花板上的灯。大家都知道天花板上的灯都是需要灯具进行装饰的,在这里我们已经引入到了装饰的概念了,好我们再来分析问题。那么灯具里面的灯泡是不变的,我们又引入了以关键的概念,就是被装饰对象。灯泡是我们一装修的时候就有的,外面的灯具是随时可以更换的,这里就形成了典型的装饰者模式的原型。请看图:

  里面的灯泡就是被装饰者,外面的灯具就是装饰者。我们已基本认识了装饰者模式的含义是什么了,下面我们就用代码来进行模拟装饰者模式。

  灯泡代码:

  • using System;  
  • using System.Collections.Generic;  
  • using System.Text;  
  • namespace ConsoleApplication1  
  • {  
  •     public class 灯泡  
  •     {  
  •         public int 灯泡型号  
  •         {  
  •             get 
  •             {  
  •                 return 10;  
  •             }  
  •         }  
  •         public string 点亮灯泡()  
  •         {  
  •             return "灯泡已经点亮";  
  •         }  
  •     }  
  • }
  •   不要问为什么灯泡类不是抽象的,在这里我们不讨论其他的原理,我们先理清装饰者模式在说,后面我会慢慢引入你们所迷惑的概念。

      这是灯泡代码,里面很简单,一个表示灯泡型号的属性和一个点亮灯泡的方法。下面我们来看装饰灯泡的灯具代码。

      矩形灯具代码:

  • using System;  
  • using System.Collections.Generic;  
  • using System.Text;  
  • namespace ConsoleApplication1  
  • {  
  •     public class 矩形灯具  
  •     {  
  •         /// <summary>   
  •         /// 灯泡的引用   
  •         /// </summary>   
  •         private 灯泡 dengpaoobject;  
  •         /// <summary>   
  •         /// 既然是灯具装饰,那么必须能容纳灯泡,所以灯具必须引用灯泡   
  •         /// </summary>   
  •         /// <param name="d">灯泡的实例</param>   
  •         public void 添加装饰的灯泡(灯泡 d)  
  •         {  
  •             dengpaoobject = d;  
  •         }  
  •         /// <summary>   
  •         /// 打开装饰了矩形灯具的感觉   
  •         /// </summary>   
  •         /// <returns>添加装饰之后的效果</returns>   
  •         public string 打开矩形灯具的效果()  
  •         {  
  •             return dengpaoobject.点亮灯泡() + ",矩形灯具所发出的光";  
  •         }  
  •     }  
  • }  
  • 51/512345>
    《2023软件测试行业现状调查报告》独家发布~

    关注51Testing

    联系我们

    快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

    法律顾问:上海兰迪律师事务所 项棋律师
    版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
    投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

    沪ICP备05003035号

    沪公网安备 31010102002173号