乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      裝飾模式(Decorator Pattern)

       漂在北方的狼 2007-03-28

      一、 裝飾(Decorator)模式

      裝飾(Decorator)模式又名包裝(Wrapper)模式[GOF95]。裝飾模式以對(duì)客戶端透明的方式擴(kuò)展對(duì)象的功能,是繼承關(guān)系的一個(gè)替代方案。

      引言

      孫悟空有七十二般變化,他的每一種變化都給他帶來一種附加的本領(lǐng)。他變成魚兒時(shí),就可以到水里游泳;他變成雀兒時(shí),就可以在天上飛行。而不管悟空怎么變化,在二郎神眼里,他永遠(yuǎn)是那只猢猻。

      裝飾模式以對(duì)客戶透明的方式動(dòng)態(tài)地給一個(gè)對(duì)象附加上更多的責(zé)任。換言之,客戶端并不會(huì)覺得對(duì)象在裝飾前和裝飾后有什么不同。裝飾模式可以在不使用創(chuàng)造更多子類的情況下,將對(duì)象的功能加以擴(kuò)展。


      二、 裝飾模式的結(jié)構(gòu)

      裝飾模式使用原來被裝飾的類的一個(gè)子類的實(shí)例,把客戶端的調(diào)用委派到被裝飾類。裝飾模式的關(guān)鍵在于這種擴(kuò)展是完全透明的。

      在孫猴子的例子里,老孫變成的魚兒相當(dāng)于老孫的子類,這條魚兒與外界的互動(dòng)要通過"委派",交給老孫的本尊,由老孫本尊采取行動(dòng)。

      裝飾模式的類圖如下圖所示:

       

      在裝飾模式中的各個(gè)角色有:

      • 抽象構(gòu)件(Component)角色:給出一個(gè)抽象接口,以規(guī)范準(zhǔn)備接收附加責(zé)任的對(duì)象。
      • 具體構(gòu)件(Concrete Component)角色:定義一個(gè)將要接收附加責(zé)任的類。
      • 裝飾(Decorator)角色:持有一個(gè)構(gòu)件(Component)對(duì)象的實(shí)例,并定義一個(gè)與抽象構(gòu)件接口一致的接口。
      • 具體裝飾(Concrete Decorator)角色:負(fù)責(zé)給構(gòu)件對(duì)象"貼上"附加的責(zé)任。


      三、 裝飾模式示例性代碼

      以下示例性代碼實(shí)現(xiàn)了裝飾模式:

       

      // Decorator pattern -- Structural example  
      using System;

      // "Component"
      abstract class Component
      {
        
      // Methods
        abstract public void Operation();
      }


      // "ConcreteComponent"
      class ConcreteComponent : Component
      {
        
      // Methods
        override public void Operation()
        
      {
          Console.WriteLine(
      "ConcreteComponent.Operation()");
        }

      }


      // "Decorator"
      abstract class Decorator : Component
      {
        
      // Fields
        protected Component component;

        
      // Methods
        public void SetComponent( Component component )
        
      {
          
      this.component = component;
        }


        
      override public void Operation()
        
      {
          
      if( component != null )
            component.Operation();
        }

      }


      // "ConcreteDecoratorA"
      class ConcreteDecoratorA : Decorator
      {
        
      // Fields
        private string addedState;

        
      // Methods
        override public void Operation()
        
      {
          
      base.Operation();
          addedState 
      = "new state";
          Console.WriteLine(
      "ConcreteDecoratorA.Operation()");
        }

      }


      // "ConcreteDecoratorB"
      class ConcreteDecoratorB : Decorator
      {
        
      // Methods
        override public void Operation()
        
      {
          
      base.Operation();
          AddedBehavior();
          Console.WriteLine(
      "ConcreteDecoratorB.Operation()");
        }


        
      void AddedBehavior()
        
      {
        }

      }


      /// 
      /// Client test
      /// 

      public class Client
      {
        
      public static void Main( string[] args )
        
      {
          
      // Create ConcreteComponent and two Decorators
          ConcreteComponent c = new ConcreteComponent();
          ConcreteDecoratorA d1 
      = new ConcreteDecoratorA();
          ConcreteDecoratorB d2 
      = new ConcreteDecoratorB();

          
      // Link decorators
          d1.SetComponent( c );
          d2.SetComponent( d1 );

          d2.Operation();
        }

      }

       

      上面的代碼在執(zhí)行裝飾時(shí)是通過SetComponent方法實(shí)現(xiàn)的,在實(shí)際應(yīng)用中,也有通過構(gòu)造函數(shù)實(shí)現(xiàn)的,一個(gè)典型的創(chuàng)建過程可能如下:

       

      new Decorator1(
         
      new Decorator2(
            
      new Decorator3(
               
      new ConcreteComponent()
               )
            )
         )

       

      裝飾模式常常被稱為包裹模式,就是因?yàn)槊恳粋€(gè)具體裝飾類都將下一個(gè)具體裝飾類或者具體構(gòu)件類包裹起來。


      四、 裝飾模式應(yīng)當(dāng)在什么情況下使用

      在以下情況下應(yīng)當(dāng)使用裝飾模式:

      1. 需要擴(kuò)展一個(gè)類的功能,或給一個(gè)類增加附加責(zé)任。
      2. 需要?jiǎng)討B(tài)地給一個(gè)對(duì)象增加功能,這些功能可以再動(dòng)態(tài)地撤銷。
      3. 需要增加由一些基本功能的排列組合而產(chǎn)生的非常大量的功能,從而使繼承關(guān)系變得不現(xiàn)實(shí)。

      五、 裝飾模式實(shí)際應(yīng)用的例子

      該例子演示了通過裝飾模式為圖書館的圖書與錄像帶添加"可借閱"裝飾。

       

      // Decorator pattern -- Real World example  
      using System;
      using System.Collections;

      // "Component"
      abstract class LibraryItem
      {
        
      // Fields
        private int numCopies;

        
      // Properties
        public int NumCopies
        
      {
          
      getreturn numCopies; }
          
      set{ numCopies = value; }
        }


        
      // Methods
        public abstract void Display();
      }


      // "ConcreteComponent"
      class Book : LibraryItem
      {
        
      // Fields
        private string author;
        
      private string title;

        
      // Constructors
        public Book(string author,string title,int numCopies)
        
      {
          
      this.author = author;
          
      this.title = title;
          
      this.NumCopies = numCopies;
        }


        
      // Methods
        public override void Display()
        
      {
          Console.WriteLine( 
      " Book ------ " );
          Console.WriteLine( 
      " Author: {0}", author );
          Console.WriteLine( 
      " Title: {0}", title );
          Console.WriteLine( 
      " # Copies: {0}", NumCopies );
        }

      }


      // "ConcreteComponent"
      class Video : LibraryItem
      {
        
      // Fields
        private string director;
        
      private string title;
        
      private int playTime;

        
      // Constructor
        public Video( string director, string title,
          
      int numCopies, int playTime )
        
      {
          
      this.director = director;
          
      this.title = title;
          
      this.NumCopies = numCopies;
          
      this.playTime = playTime;
        }


        
      // Methods
        public override void Display()
        
      {
          Console.WriteLine( 
      " Video ----- " );
          Console.WriteLine( 
      " Director: {0}", director );
          Console.WriteLine( 
      " Title: {0}", title );
          Console.WriteLine( 
      " # Copies: {0}", NumCopies );
          Console.WriteLine( 
      " Playtime: {0}", playTime );
        }

      }


      // "Decorator"
      abstract class Decorator : LibraryItem
      {
        
      // Fields
        protected LibraryItem libraryItem;

        
      // Constructors
        public Decorator ( LibraryItem libraryItem )
        
      this.libraryItem = libraryItem; }

        
      // Methods
        public override void Display()
        
      { libraryItem.Display(); }
      }


      // "ConcreteDecorator"
      class Borrowable : Decorator
      {
        
      // Fields
        protected ArrayList borrowers = new ArrayList();

        
      // Constructors
        public Borrowable( LibraryItem libraryItem )
          : 
      base( libraryItem ) {}

        
      // Methods
        public void BorrowItem( string name )
        
      {
          borrowers.Add( name );
          libraryItem.NumCopies
      --;
        }


        
      public void ReturnItem( string name )
        
      {
          borrowers.Remove( name );
          libraryItem.NumCopies
      ++;
        }


        
      public override void Display()
        
      {
          
      base.Display();
          
      foreachstring borrower in borrowers )
            Console.WriteLine( 
      " borrower: {0}", borrower );
        }

      }

       
      /// 
      ///  DecoratorApp test
      /// 

      public class DecoratorApp
      {
        
      public static void Main( string[] args )
        
      {
          
      // Create book and video and display
          Book book = new Book( "Schnell""My Home"10 );
          Video video 
      = new Video( "Spielberg",
            
      "Schindler‘s list"2360 );
          book.Display();
          video.Display();

          
      // Make video borrowable, then borrow and display
          Console.WriteLine( " Video made borrowable:" );
          Borrowable borrowvideo 
      = new Borrowable( video );
          borrowvideo.BorrowItem( 
      "Cindy Lopez" );
          borrowvideo.BorrowItem( 
      "Samuel King" );

          borrowvideo.Display();
        }

      }

       


      六、 使用裝飾模式的優(yōu)點(diǎn)和缺點(diǎn)

      使用裝飾模式主要有以下的優(yōu)點(diǎn):

      1. 裝飾模式與繼承關(guān)系的目的都是要擴(kuò)展對(duì)象的功能,但是裝飾模式可以提供比繼承更多的靈活性。
      2. 通過使用不同的具體裝飾類以及這些裝飾類的排列組合,設(shè)計(jì)師可以創(chuàng)造出很多不同行為的組合。
      3. 這種比繼承更加靈活機(jī)動(dòng)的特性,也同時(shí)意味著裝飾模式比繼承更加易于出錯(cuò)。

      使用裝飾模式主要有以下的缺點(diǎn):

      由于使用裝飾模式,可以比使用繼承關(guān)系需要較少數(shù)目的類。使用較少的類,當(dāng)然使設(shè)計(jì)比較易于進(jìn)行。但是,在另一方面,使用裝飾模式會(huì)產(chǎn)生比使用繼承關(guān)系更多的對(duì)象。更多的對(duì)象會(huì)使得查錯(cuò)變得困難,特別是這些對(duì)象看上去都很相像。


      七、 模式實(shí)現(xiàn)的討論

      大多數(shù)情況下,裝飾模式的實(shí)現(xiàn)都比上面定義中給出的示意性實(shí)現(xiàn)要簡(jiǎn)單。對(duì)模式進(jìn)行簡(jiǎn)化時(shí)需要注意以下的情況:

      (1)一個(gè)裝飾類的接口必須與被裝飾類的接口相容。

      (2)盡量保持Component作為一個(gè)"輕"類,不要把太多的邏輯和狀態(tài)放在Component類里。

      (3)如果只有一個(gè)ConcreteComponent類而沒有抽象的Component類(接口),那么Decorator類經(jīng)??梢允荂oncreteComponent的一個(gè)子類。如下圖所示:

       

      (4)如果只有一個(gè)ConcreteDecorator類,那么就沒有必要建立一個(gè)單獨(dú)的Decorator類,而可以把Decorator和ConcreteDecorator的責(zé)任合并成一個(gè)類。


      八、 透明性的要求

      透明的裝飾模式

      裝飾模式通常要求針對(duì)抽象編程。裝飾模式對(duì)客戶端的透明性要求程序不要聲明一個(gè)ConcreteDecorator類型的變量,而應(yīng)當(dāng)聲明一個(gè)Component類型的變量。換言之,下面的做法是對(duì)的:

       

      Component c = new ConcreteComponent();
      Component c1 
      = new ConcreteDecorator1(c);
      Component c2 
      = new ConcreteDecorator(c1);

       

      而下面的做法是不對(duì)的:

       

      ConcreteComponent c = new ConcreteDecorator();

       

      這就是前面所說的,裝飾模式對(duì)客戶端是完全透明的含義。

      用孫悟空的例子來說,必須永遠(yuǎn)把孫悟空的所有變化都當(dāng)成孫悟空來對(duì)待,而如果把老孫變成的雀兒當(dāng)成雀兒,而不是老孫,那就被老孫騙了,而這是不應(yīng)當(dāng)發(fā)生的。

      下面的做法是不對(duì)的:

       

      大圣本尊 c = new 大圣本尊();
      雀兒 bird 
      = new 雀兒 (c);

       

      半透明的裝飾模式

      然而,純粹的裝飾模式很難找到。裝飾模式的用意是在不改變接口的前提下,增強(qiáng)所考慮的類的性能。在增強(qiáng)性能的時(shí)候,往往需要建立新的公開的方法。即 便是在孫大圣的系統(tǒng)里,也需要新的方法。比如齊天大圣類并沒有飛行的能力,而雀兒有。這就意味著雀兒應(yīng)當(dāng)有一個(gè)新的fly()方法。

      這就導(dǎo)致了大多數(shù)的裝飾模式的實(shí)現(xiàn)都是"半透明"(semi-transparent)的,而不是完全"透明"的。換言之,允許裝飾模式改變接口, 增加新的方法。即聲明ConcreteDecorator類型的變量,從而可以調(diào)用ConcreteDecorator類中才有的方法:

       

      齊天大圣 c = new 大圣本尊();
      雀兒 bird 
      = new 雀兒(c);
      bird.fly();

       

      齊天大圣接口根本沒有fly()這個(gè)方法,而雀兒接口里有這個(gè)方法。


      九、 裝飾模式在.NET中的應(yīng)用

      .net中存在如下類模型:

       

      下面的代碼段用來將XmlDocument的內(nèi)容格式輸出。我們可以體會(huì)Decorator模式在這里所起的作用。

       

       

      // 生成ConcreteComponent(內(nèi)存流ms)
      MemoryStream ms = new MemoryStream();

      // 用XmlTextWriter對(duì)內(nèi)存流 ms 進(jìn)行裝飾
      // 此處使用了半透明的裝飾模式
      XmlTextWriter xtw = new XmlTextWriter(ms, Encoding.UTF8);
      xtw.Formatting 
      = Formatting.Indented;

      // 對(duì)裝飾xtw的操作會(huì)轉(zhuǎn)而操作本體-內(nèi)存流ms
      xmlDoc.Save(xtw);

      byte[] buf = ms.ToArray();
      txtResult.Text 
      = Encoding.UTF8.GetString(buf,0,buf.Length);
      xtw.Close();

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多