設計模式系列-裝飾模式


        下班回家無聊在加上本命年有些不太順利,決定看男人幫打發下班的無聊時間,點擊第十八集,開場白:

        我們生活在這個 一秒鍾一個變化的世界里 有時候友情比愛情更為可靠 朋友可以在你最艱苦的時候 默默守候 在你一切平安的時候 雲淡風輕的離開 愛人有事相反 男人和女人的友情又不一樣 男人如此粗暴而簡單 女人的友情溫婉而復雜 當男女的友情 遇到了男女的愛情 就會迅速變成兩個陣營!
        尾語:我們都需要愛情 就像我們都需要友情一樣 我們在這個世界上不斷地找尋 因為我們缺一不可

       1.場景模擬

        這樣讓想起了老李,我跟老李是很要好的哥們,當然他不像我還是光棍,所以他不光有友情還有愛情了,不過,就在最近幾天他們吵架啦,什么原因?就不多說啦,總之身為男人的老李還是決定主動認錯挽回女方了,但是挽回女方不像約會打扮的靚麗是一方面,重要的是道歉的誠意呀,例如:一封道歉信,一束玫瑰花,帶上第一次女方送的圍巾來表示誠意等等。我想這樣的打扮加上誠懇的態度,一定會成功歸來啦!       

        那么我們就用代碼來實現吧: 

   public  class MrLi
    {
         private  const  string name =  " limou ";

         ///   <summary>
        
///  道歉信
        
///   </summary>
         public  void Letters()
        {
            Console.Write( " 道歉信  ");
        }

         ///   <summary>
        
///  玫瑰花
        
///   </summary>
         public  void Rose()
        {
            Console.Write( " 玫瑰花  ");
        }

         ///   <summary>
        
///  圍巾
        
///   </summary>
         public  void Scarf()
        {
            Console.Write( " 女友送的圍巾  ");
        }

         ///   <summary>
        
///  帶上挽回女友的東西
        
///   </summary>
         public  void Operation()
        {
            Console.WriteLine( " 帶上: ");
             this.Letters();
             this.Rose();
             this.Scarf();
        }
    }
   static  void Main( string[] args)
  {
        MrLi li =  new MrLi();
         // 帶上東西
        li.Operation();
        Console.WriteLine();
  }

 

        運行結果如下:

       

        剛完成以上代碼,就接到老李的電話說成功啦,用這招還真管用啊,我說那我們明天晚上吃飯慶祝一下吧?老李說:“不行啦,我們剛和好,明天晚上我只屬於我女朋友啦。我要跟她一起吃飯噢!”,我暈,重色輕友啊!

        那他明天跟女友約會肯定不會再是這一套了,肯定不管用了,如果他明天繼續帶上玫瑰花,帶上太陽鏡和圍巾呢?這個時候我們剛才實現的類好像就不能滿足了,怎么辦呢?最爛的辦法就是在MrLi類中加入一個帶上太陽鏡的方法,為什么是最爛的方法呢?因為他違背了面向對象原則中的開放-封閉原則。那么什么是開放封閉原則呢?

        開放封閉原則:類可擴展,但不可修改。

        那么如何能支持MrLi的裝扮可以自定義隨意變換呢?不要着急先看看裝飾模式吧!

        2.裝飾模式

         裝飾模式:裝飾模式是動態的給對象增加責任,對擴展來功能說,裝飾模式提供了比繼承更靈活的方案

         裝飾模式類圖如下:

        Component類:用來抽象裝飾對象與被裝飾對象的共同的裝飾行為。

        ConcreteComponent類:是一個被裝飾的主對象。

        Decorator類:是一個用來裝飾的抽象類,包含了Component類的實例與實現了裝飾與被裝飾對象的共同行為,包含Component類實例表示將來具體的裝飾類都有一個明確的被裝飾對象

        ConcreteDecratorAConcreteDecratorB類:是具體裝飾類實例,該對象實現了抽象的Decorator類,包含一個被裝飾對象用來裝飾此對象。

        裝飾模式代碼如下:

   ///   <summary>
    
///  裝飾行為的抽象
    
///   </summary>
     public  abstract  class Component
    {
         // 操作
         public  abstract  void Operation();
    }

     ///   <summary>
    
///  被裝飾的對象
    
///   </summary>
     public  class ConcreteComponent : Component
    {
         public  override  void Operation()
        {
            Console.WriteLine( " 具體對象的操作 ");
        }
    }

     ///   <summary>
    
///  抽象的裝飾類
    
///   </summary>
     public  abstract  class Decorator : Component
    {
         protected Component component;

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

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

     ///   <summary>
    
///  具體的裝飾類
    
///   </summary>
     public  class ConcreteDecoratorA : Decorator
    {
         private  void AddedBehaviorA()
        {
            Console.WriteLine( " 裝飾A ");
        }

         public  override  void Operation()
        {
             base.Operation();
            AddedBehaviorA();
        }
    }

     public  class ConcreteDecoratorB : Decorator
    {
         private  void AddedBehaviorB()
        {
            Console.WriteLine( " 裝飾B ");
        }

         public  override  void Operation()
        {
             base.Operation();
            AddedBehaviorB();
        }
    }

        主函數調用如下:

        static  void Main( string[] args)
        {
             // 定義被裝飾對象 主裝飾對象
            ConcreteComponent cc =  new ConcreteComponent();
             // 定義具體裝飾對象A 主對象上的裝飾
            ConcreteDecoratorA cda =  new ConcreteDecoratorA();
             // 定義具體裝飾對象A 主對象上的裝飾
            ConcreteDecoratorB cdb =  new ConcreteDecoratorB();

             // 裝飾對象A 裝扮主對象cc
            cda.SetComponent(cc);
             // 裝飾對象B 裝扮裝飾對象A
            cdb.SetComponent(cda);
             // 開始裝扮
            cdb.Operation();

             // 第二種裝扮
            
// 裝飾對象B 裝扮主對象cc
            cdb.SetComponent(cc);
             // 裝飾對象A 裝扮裝飾對象B
            cda.SetComponent(cdb);
             // 開始裝扮
            cda.Operation();
      }

        可以看到,有了裝飾模式,我們可以輕易的增加裝飾對象,並且靈活的組織裝飾對象裝扮的順序,那如果我們用裝飾模式實現我們第一部分的場景應該如何呢?

        3.裝飾模式的靈活運用

         那我們設計的類圖如下:

         代碼實現如下:

    ///   <summary>
    
///  打扮的抽象類
    
///   </summary>
     public  abstract  class DressUp
    {
         // 開始打扮
         public  abstract  void ToDressUp();
    }

     ///   <summary>
    
///  被裝飾的對象,老李,圍巾等飾品都是裝飾在他身上
    
///   </summary>
     public  class MrLi : DressUp
    {
         private  const  string name =  " limou ";

         ///   <summary>
        
///  開始打扮
        
///   </summary>
         public  override  void ToDressUp()
        {
            Console.WriteLine( " {0}開始打扮如下飾品: ",name);
        }
    }

     ///   <summary>
    
///  裝飾品抽象類
    
///   </summary>
     public  abstract  class Decorator:DressUp
    {
         // 實現一個被裝飾對象用來記錄裝飾誰
         protected DressUp component =  null;

         ///   <summary>
        
///  設置被打扮對象
        
///   </summary>
        
///   <param name="com"></param>
         public  void SetDressUp(DressUp com)
        {
             this.component = com;
        }

         ///   <summary>
        
///  默認的裝扮實現
        
///   </summary>
         public  override  void ToDressUp()
        {
             if (component !=  null)
            {
                component.ToDressUp();
            }
        }
    }

     ///   <summary>
    
///  道歉信裝飾類
    
///   </summary>
     public  class Letters : Decorator
    {
         ///   <summary>
        
///  開始打扮
        
///   </summary>
         public  override  void ToDressUp()
        {
             base.ToDressUp();
            Console.Write( " 道歉信  ");
        }
    }

     ///   <summary>
    
///  玫瑰花裝飾類
    
///   </summary>
     public  class Rose : Decorator
    {
         ///   <summary>
        
///  開始打扮
        
///   </summary>
         public  override  void ToDressUp()
        {
             base.ToDressUp();
            Console.Write( " 玫瑰花  ");
        }
    }

     ///   <summary>
    
///  圍巾裝飾類
    
///   </summary>
     public  class Scarf : Decorator
    {
         ///   <summary>
        
///  開始打扮
        
///   </summary>
         public  override  void ToDressUp()
        {
             base.ToDressUp();
            Console.Write( " 女友送的圍巾  ");
        }
    }

     ///   <summary>
    
///  太陽鏡裝飾類,可以添加需要的裝飾類
    
///   </summary>
     public  class Sunglasses :Decorator
    {
         ///   <summary>
        
///  開始打扮
        
///   </summary>
         public  override  void ToDressUp()
        {
             base.ToDressUp();
            Console.Write( " 太陽眼鏡  ");
        }
    }

    主函數調用如下:

         static  void Main( string[] args)
        {
            MrLi li =  new MrLi();

             // 第一天道歉的打扮
            Console.WriteLine( " 第一天道歉的打扮: ");
             // 道歉信
            Letters letters =  new Letters();
             // 玫瑰花
            Rose rose =  new Rose();
             // 女友送的圍巾
            Scarf scarf =  new Scarf();

             // 打扮道歉信
            letters.SetDressUp(li);
             // 打扮玫瑰
            rose.SetDressUp(letters);
             // 打扮圍巾
            scarf.SetDressUp(rose);
             // 開始打扮
            scarf.ToDressUp();
            Console.WriteLine();
            Console.WriteLine( " -------------------------------------- ");
             // 第二天約會的打扮
            Console.WriteLine( " 第二天約會的打扮 ");
             // 道歉信
            Letters let =  new Letters();
             // 太陽鏡
            Sunglasses sunglasses =  new Sunglasses();
             // 女友送的圍巾
            Scarf sca =  new Scarf();

             // 打扮道歉信
            let.SetDressUp(li);
             // 打扮玫瑰
            sunglasses.SetDressUp(let);
             // 打扮圍巾
            sca.SetDressUp(sunglasses);
             // 開始打扮
            sca.ToDressUp();
            Console.WriteLine();
      }

     運行結果如下:

   

    這樣利用裝飾模式就可以有效的解決將來對新裝飾品的擴展而無需去修改原先的類,完全的滿足了開放封閉原則。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM