设计模式系列-装饰模式


        下班回家无聊在加上本命年有些不太顺利,决定看男人帮打发下班的无聊时间,点击第十八集,开场白:

        我们生活在这个 一秒钟一个变化的世界里 有时候友情比爱情更为可靠 朋友可以在你最艰苦的时候 默默守候 在你一切平安的时候 云淡风轻的离开 爱人有事相反 男人和女人的友情又不一样 男人如此粗暴而简单 女人的友情温婉而复杂 当男女的友情 遇到了男女的爱情 就会迅速变成两个阵营!
        尾语:我们都需要爱情 就像我们都需要友情一样 我们在这个世界上不断地找寻 因为我们缺一不可

       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