zoukankan      html  css  js  c++  java
  • NET框架中的 Decorator 和 Strategy 模式

    NET框架中的 Decorator 和 Strategy 模式

            应用场景:net 框架下的TextWriter,HtmlTextWriter,CssTextWriter,IndentedTextWriter 等
            先看一下Decorator 模式结构图:


        NET 下的 Decorator 模式(TextWriter及其派生类):


       
    虽然图形有所不同,但大致结构相似。

        这里就大概先分析一下吧。

        TextWriter 作为 一个抽象类定义形式如下:
     
        public abstract class TextWriter : MarshalByRefObject, IDisposable
        {
          .....

          public virtual Write(...);
          .....
          public virtual WriteLine(...);
          .....
        }
       
        里面的Write及WriteLine函数全部是虚方法,因此可以在子类中被重写, 我们一会能看到子类中的这些方法会在调用基类方法之前
    进行一些其它的操作:)

        派生类(以HtmlTextWriter 为例)声明如下:

        public class HtmlTextWriter : TextWriter
        {
          .....

          public virtual Write(...);
          .....
          public virtual WriteLine(...);
          .....
        }
     
        这里用其中的Write(bool value)函数说明如下:

        public override void Write(bool value)
        {
         if (this.tabsPending)             --->先进行“添加职责”操作
         {
                this.OutputTabs();            
         }
            this.writer.Write(value);         --->最后调用基类方法
        }

       
        这里就是这种模式所说的"在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。"

        备注:1 .CssTextWriter, SyncTextWriter 类只是将TextWriter作为构造参数传入,未进行"添加职责"的处理,同时
         这两个类的声明如下:
      internal sealed class CssTextWriter : TextWriter
      internal sealed class SyncTextWriter : TextWriter, IDisposable

     
             2. IndentedTextWriter 类与HtmlTextWriter在Write函数中大同小异, 代码如下:
      public override void Write(bool value)
      {
          this.OutputTabs();
          this.writer.Write(value);
      }

             3. StreamWriter,StringWriter 的实现与其它的Writer类有差异,可参考的使用方法如下:
                IndentedTextWriter tw = new IndentedTextWriter(new StreamWriter(_strFileName, false), "");
         ......
         HtmlTextWriter  htw = new IndentedTextWriter(new   StreamWriter(memoryStream,   Encoding.GetEncoding("GB18030")));
                ......
         HtmlTextWriter writer=new HtmlTextWriter(new System.IO.StringWriter());
                ......

         总体上说,Decorator 结构还是很清楚的,也很好理解。这里再把这种模式的意图和适用性拷贝如下,以加深理解:

         意图:  动态地给一个对象添加一些额外的职责。就增加功能来说,比生成子类更为灵活。

         适用性: 1. 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
          2. 处理那些可以撤消的职责。
          3. 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产
      生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于
      生成子类。 


         相关参考: http://topic.csdn.net/t/20040325/09/2883578.html
            http://hi.baidu.com/xiao0856/blog/item/e96479d0855fb18ea0ec9cc5.html
       

     

        
     
          下面,接着再说一下这个架构下的另一个模式 Strategy
     
          还是先看一下Strategy 模式的结构图:


          NET 下的 Strategy 模式(Stream及其派生类):

              

          相信大家已看清楚了,基本上调用的流程如下:
     
          StreamWriter 对象实例--->Write--->Flush(bool flushStream, bool flushEncoder)

          Flush函数的实现如下:

          private void Flush(bool flushStream, bool flushEncoder)
          {
         if (this.stream == null)
         {
             __Error.WriterClosed();
         }

         if (((this.charPos != 0) || flushStream) || flushEncoder)
         {

             if (!this.haveWrittenPreamble)
             {
                 this.haveWrittenPreamble = true;
                 byte[] preamble = this.encoding.GetPreamble();
                 if (preamble.Length > 0)
                 {
                     this.stream.Write(preamble, 0, preamble.Length);    //调用指定的STREAM对象的write函数
                 }
             }
                    int count = this.encoder.GetBytes(this.charBuffer, 0, this.charPos, this.byteBuffer, 0, flushEncoder);
             this.charPos = 0;
             if (count > 0)
             {
                 this.stream.Write(this.byteBuffer, 0, count);   //调用指定的STREAM对象的write函数
             }
             if (flushStream)
             {
                 this.stream.Flush();
             }
         }
     }

          到这里大家就该明白了吧:)
          调用的方式可以是这样(以FileStream为例):
     FileStream fs = new FileStream(Server.MapPath(".")+"\\test.txt",FileMode.Create,FileAccess.Write);
            StreamWriter sw = new StreamWriter(fs);
            sw.WriteLine("这里是内容");
            ......
            sw.Close();
            fs.Close();

          这里再把这种模式的意图和适用性拷贝如下,以加深理解:
          意图:    定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
          适用性:  1. 许多相关的类仅仅是行为有异。“策略”提供了一种用多个行为中的一个行为来配置一个类的方法。
            2. 需要使用一个算法的不同变体。例如,你可能会定义一些反映不同的空间/时间权衡的算法。当这些变体实现为一个算法的类层次时[ H O 8 7 ] ,可以使用策略模式。
            3. 算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构。
            4. 一个类定义了多种行为, 并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的S t r a t e g y 类中以代替这些条件语句。 

     

            推广:其实将上面的类图中的StreamWriter 换成 StreamReader, 也是这个模式,只不过这两个类在.net 共存而已。


            这里把这两个模式一起抬出来只是因为在分析类似Writer,Reader类时同时发现的,为了体现整个性才一起搬出来:)

            因为这篇文章的内容只是学习.net框架时的“副产品”,因此里面的内容可读性不强,同时肯定会有偏颇之
    处。如果大家有不同意见,希望回复本人,以纠正本人的误解,希望不要误导大家:)
     
      

     

     

  • 相关阅读:
    常用Linux命令
    SQL必知必会-笔记
    【ubuntu】install openbox+tint2+bmenu on ubuntu12.04.4
    【ruby】安装Ruby
    【ruby】快速安装gems的方法
    【sinatra】设置默认的端口
    【sinatra】修改默认ip绑定
    【sinatra】结合Padrino framework
    【sinatra】安装测试
    【rails3教材】博客构建过程2
  • 原文地址:https://www.cnblogs.com/daizhj/p/837958.html
Copyright © 2011-2022 走看看