c#设计模式之装饰者模式

装饰者模式是动态地扩展一个对象的功能。下面看一个例子:网页中要使用图片,我要上传图片,具体规则:

1、对于一些比较大,甚至几兆的图片,上传后,生成缩略图,生成缩略图可以按照指定尺寸,或者固定宽,高按比例缩放。

2、对于tif格式的图片,通常都比较大,需要转jpg格式的图片,或者转jpg格式后,若发现图片还是很大,再进行压缩处理。

3、对于合适大小的图片,上传上去不做处理。

首先定义一个抽象类,用来实现上传:

 1  public abstract class AbstractUpload
 2     {
 3        
 4         public Stream FileStream { set; get; }
 5 
 6 
 7         public UploadInfo Result { set; get; }
 8  
 9         public abstract byte[] GetContent();
10 
11         public virtual UploadInfo Upload(string listTitle, string fileName, bool isRename = true){
12           //具体上传方法
13         }
14          public virtual UploadInfo GetResult(){
15 
16            //获取上传结果
17          }
18 }

然后定义装饰者的抽象类:

1  public abstract class UploadDecrator:AbstractUpload
2     {
3         public AbstractUpload UpLoader { set; get; }
4 
5     }

下面是按照规定尺寸生成缩略图:

 public class ThumbUpload:UploadDecrator
    {

        public ThumbImageInfo ImgInfo { set; get; }

         public ThumbUpload(AbstractUpload upload,ThumbImageInfo imgInfo)
        {

            this.UpLoader = upload;

            this.ImgInfo = imgInfo;
        }

        public override byte[] GetContent()
        {
           var img= MakeSmallPic();

           return StringUlity.ImgToByte(img);
        }
}

接着,我们实现tif图片的处理:

 1  public class TifImageUpload : UploadDecrator
 2     {
 3         public ThumbImageInfo ImgInfo { set; get; }
 4 
 5         public bool IsCacularMode { set; get; }
 6 
 7         public TifImageUpload(AbstractUpload upload, ThumbImageInfo imgInfo, bool isCacularMode)
 8         {
 9 
10             this.UpLoader = upload;
11 
12             this.ImgInfo = imgInfo;
13 
14             this.IsCacularMode = isCacularMode;
15         }
16 
17         public TifImageUpload(AbstractUpload upload, bool isCacularMode)
18         {
19 
20             this.UpLoader = upload;
21             this.IsCacularMode = isCacularMode;
22         }
23 
24 
25         public override byte[] GetContent()
26         {
27             var img = MakeSmallPic();
28 
29             return StringUlity.ImgToByte(img);
30         }
31 }

看到这儿,可能有人会有疑问,具体的类,为什么不直接继承AbstractUpload呢?因为AbstractUpload类是一个抽象类,它还为其它的各种文件上传使用,为了不影响这个基础的抽象类,所以我们单独定义自己的装饰者抽象类。

看看客户端是如何调用的?

这个是上传tif图片,处理为jpg格式,然后再上传。

看到这里,是不是觉得FileStreamUpload f ,这个有点问题,与构造函数的类型不一致呢?且看下文:

 1   /// <summary>
 2     /// 上传文件
 3     /// </summary>
 4     public class FileStreamUpload : AbstractUpload
 5     {
 6 
 7         public FileStreamUpload(Stream stream)
 8         {
 9 
10             this.FileStream = stream;
11         }
12 
13         public override byte[] GetContent()
14         {
15             int iLength = (int)FileStream.Length;
16 
17 
18             Byte[] filecontent=null;
19 
20             if (iLength > 0)
21             {
22                 filecontent = new byte[iLength];
23                 FileStream.Read(filecontent, 0, iLength);
24             }
25             return filecontent;
26         }
27     }

这个是所有文件上传类,也继承自抽象类AbstractUpload。且看这些类之间的关系:

上图是装饰者模式的uml图,其巧妙之处在于装饰者类UploadDecrator组合了自己的一个基类。这是一个组合优于继承的设计原则体现。说到这儿,我们回顾下面向对象设计的基本原则:

1、单一职责:一个类只做一件事情。

2、开闭原则:对修改关闭,对扩展开放。

3、依赖倒置:高层模块不应该依赖于低层模块,两者均依赖于抽象。这个抽象是从高层模块抽象出来的。

4、里氏替换:子类可以替换父类,可以在运行时决定是哪个子类替代父类实现,它是实现开闭原则的重要方式。

5、接口隔离:尽量使用“瘦”接口。

6、迪米特法则:最少知识原则,一个对象对其它对象有尽可能少的了解。

7、组合/聚合复用原则:组合优于继承。

前5个为基本原则。设计模式会体现这些设计原则,所以我们必须得好好参悟。

    

 

posted @ 2016-09-30 17:30  micDavid  阅读(1362)  评论(0编辑  收藏  举报