设计模式系列-装饰模式

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

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

       1.场景模拟

        这样让想起了老李,我跟老李是很要好的哥们,当然他不像我还是光棍,所以他不光有友情还有爱情了,不过,就在最近几天他们吵架啦,什么原因?就不多说啦,总之身为男人的老李还是决定主动认错挽回女方了,但是挽回女方不像约会打扮的靓丽是一方面,重要的是道歉的诚意呀,例如:一封道歉信,一束玫瑰花,带上第一次女方送的围巾来表示诚意等等。我想这样的打扮加上诚恳的态度,一定会成功归来啦!       

        那么我们就用代码来实现吧: 

 
 
  1. public class MrLi  
  2.    {  
  3.        private const string name = "limou";  
  4.  
  5.        /// <summary>  
  6.        /// 道歉信  
  7.        /// </summary>  
  8.        public void Letters()  
  9.        {  
  10.            Console.Write("道歉信 ");  
  11.        }  
  12.  
  13.        /// <summary>  
  14.        /// 玫瑰花  
  15.        /// </summary>  
  16.        public void Rose()  
  17.        {  
  18.            Console.Write("玫瑰花 ");  
  19.        }  
  20.  
  21.        /// <summary>  
  22.        /// 围巾  
  23.        /// </summary>  
  24.        public void Scarf()  
  25.        {  
  26.            Console.Write("女友送的围巾 ");  
  27.        }  
  28.  
  29.        /// <summary>  
  30.        /// 带上挽回女友的东西  
  31.        /// </summary>  
  32.        public void Operation()  
  33.        {  
  34.            Console.WriteLine("带上:");  
  35.            this.Letters();  
  36.            this.Rose();  
  37.            this.Scarf();  
  38.        }  
  39.    }  
  40.  static void Main(string[] args)  
  41.  {  
  42.        MrLi li = new MrLi();  
  43.        //带上东西  
  44.        li.Operation();  
  45.        Console.WriteLine();  
  46.  }  

         运行结果如下:        

        刚完成以上代码,就接到老李的电话说成功啦,用这招还真管用啊,我说那我们明天晚上吃饭庆祝一下吧?老李说:“不行啦,我们刚和好,明天晚上我只属于我女朋友啦。我要跟她一起吃饭噢!”,我晕,重色轻友啊!

        那他明天跟女友约会肯定不会再是这一套了,肯定不管用了,如果他明天继续带上玫瑰花,带上太阳镜和围巾呢?这个时候我们刚才实现的类好像就不能满足了,怎么办呢?最烂的办法就是在MrLi类中加入一个带上太阳镜的方法,为什么是最烂的方法呢?因为他违背了面向对象原则中的开放-封闭原则。那么什么是开放封闭原则呢?

        开放封闭原则:类可扩展,但不可修改。

        那么如何能支持MrLi的装扮可以自定义随意变换呢?不要着急先看看装饰模式吧!

        2.装饰模式

         装饰模式:装饰模式是动态的给对象增加责任,对扩展来功能说,装饰模式提供了比继承更灵活的方案

         装饰模式类图如下:

        Component类:用来抽象装饰对象与被装饰对象的共同的装饰行为。

        ConcreteComponent类:是一个被装饰的主对象。

        Decorator类:是一个用来装饰的抽象类,包含了Component类的实例与实现了装饰与被装饰对象的共同行为,包含Component类实例表示将来具体的装饰类都有一个明确的被装饰对象

        ConcreteDecratorAConcreteDecratorB类:是具体装饰类实例,该对象实现了抽象的Decorator类,包含一个被装饰对象用来装饰此对象。

        装饰模式代码如下:

 
 
  1. /// <summary>  
  2.    /// 装饰行为的抽象  
  3.    /// </summary>  
  4.    public abstract class Component  
  5.    {  
  6.        //操作  
  7.        public abstract void Operation();  
  8.    }  
  9.  
  10.    /// <summary>  
  11.    /// 被装饰的对象  
  12.    /// </summary>  
  13.    public class ConcreteComponent : Component  
  14.    {  
  15.        public override void Operation()  
  16.        {  
  17.            Console.WriteLine("具体对象的操作");  
  18.        }  
  19.    }  
  20.  
  21.    /// <summary>  
  22.    /// 抽象的装饰类  
  23.    /// </summary>  
  24.    public abstract class Decorator : Component  
  25.    {  
  26.        protected Component component;  
  27.  
  28.        public void SetComponent(Component component)  
  29.        {  
  30.            this.component = component;  
  31.        }  
  32.  
  33.        public override void Operation()  
  34.        {  
  35.            if (component != null)  
  36.            {  
  37.                component.Operation();  
  38.            }  
  39.        }  
  40.    }  
  41.  
  42.    /// <summary>  
  43.    /// 具体的装饰类  
  44.    /// </summary>  
  45.    public class ConcreteDecoratorA : Decorator  
  46.    {  
  47.        private void AddedBehaviorA()  
  48.        {  
  49.            Console.WriteLine("装饰A");  
  50.        }  
  51.  
  52.        public override void Operation()  
  53.        {  
  54.            base.Operation();  
  55.            AddedBehaviorA();  
  56.        }  
  57.    }  
  58.  
  59.    public class ConcreteDecoratorB : Decorator  
  60.    {  
  61.        private void AddedBehaviorB()  
  62.        {  
  63.            Console.WriteLine("装饰B");  
  64.        }  
  65.  
  66.        public override void Operation()  
  67.        {  
  68.            base.Operation();  
  69.            AddedBehaviorB();  
  70.        }  
  71.    }  
         主函数调用如下:
  
  
  1. static void Main(string[] args)  
  2.       {  
  3.           //定义被装饰对象 主装饰对象  
  4.           ConcreteComponent cc = new ConcreteComponent();  
  5.           //定义具体装饰对象A 主对象上的装饰  
  6.           ConcreteDecoratorA cda = new ConcreteDecoratorA();  
  7.           //定义具体装饰对象A 主对象上的装饰  
  8.           ConcreteDecoratorB cdb = new ConcreteDecoratorB();  
  9.  
  10.           //装饰对象A 装扮主对象cc  
  11.           cda.SetComponent(cc);  
  12.           //装饰对象B 装扮装饰对象A  
  13.           cdb.SetComponent(cda);  
  14.           //开始装扮  
  15.           cdb.Operation();  
  16.  
  17.           //第二种装扮  
  18.           //装饰对象B 装扮主对象cc  
  19.           cdb.SetComponent(cc);  
  20.           //装饰对象A 装扮装饰对象B  
  21.           cda.SetComponent(cdb);  
  22.           //开始装扮  
  23.           cda.Operation();  
  24.     }  
              可以看到,有了装饰模式,我们可以轻易的增加装饰对象,并且灵活的组织装饰对象装扮的顺序,那如果我们用装饰模式实现我们第一部分的场景应该如何呢?

        3.装饰模式的灵活运用

         那我们设计的类图如下:

         代码实现如下:

 
 
  1. /// <summary>  
  2.   /// 打扮的抽象类  
  3.   /// </summary>  
  4.   public abstract class DressUp  
  5.   {  
  6.       //开始打扮  
  7.       public abstract void ToDressUp();  
  8.   }  
  9.  
  10.   /// <summary>  
  11.   /// 被装饰的对象,老李,围巾等饰品都是装饰在他身上  
  12.   /// </summary>  
  13.   public class MrLi : DressUp  
  14.   {  
  15.       private const string name = "limou";  
  16.  
  17.       /// <summary>  
  18.       /// 开始打扮  
  19.       /// </summary>  
  20.       public override void ToDressUp()  
  21.       {  
  22.           Console.WriteLine("{0}开始打扮如下饰品:",name);  
  23.       }  
  24.   }  
  25.  
  26.   /// <summary>  
  27.   /// 装饰品抽象类  
  28.   /// </summary>  
  29.   public abstract class Decorator:DressUp  
  30.   {  
  31.       //实现一个被装饰对象用来记录装饰谁  
  32.       protected DressUp component = null;  
  33.  
  34.       /// <summary>  
  35.       /// 设置被打扮对象  
  36.       /// </summary>  
  37.       /// <param name="com"></param>  
  38.       public void SetDressUp(DressUp com)  
  39.       {  
  40.           this.component = com;  
  41.       }  
  42.  
  43.       /// <summary>  
  44.       /// 默认的装扮实现  
  45.       /// </summary>  
  46.       public override void ToDressUp()  
  47.       {  
  48.           if (component != null)  
  49.           {  
  50.               component.ToDressUp();  
  51.           }  
  52.       }  
  53.   }  
  54.  
  55.   /// <summary>  
  56.   /// 道歉信装饰类  
  57.   /// </summary>  
  58.   public class Letters : Decorator  
  59.   {  
  60.       /// <summary>  
  61.       /// 开始打扮  
  62.       /// </summary>  
  63.       public override void ToDressUp()  
  64.       {  
  65.           base.ToDressUp();  
  66.           Console.Write("道歉信 ");  
  67.       }  
  68.   }  
  69.  
  70.   /// <summary>  
  71.   /// 玫瑰花装饰类  
  72.   /// </summary>  
  73.   public class Rose : Decorator  
  74.   {  
  75.       /// <summary>  
  76.       /// 开始打扮  
  77.       /// </summary>  
  78.       public override void ToDressUp()  
  79.       {  
  80.           base.ToDressUp();  
  81.           Console.Write("玫瑰花 ");  
  82.       }  
  83.   }  
  84.  
  85.   /// <summary>  
  86.   /// 围巾装饰类  
  87.   /// </summary>  
  88.   public class Scarf : Decorator  
  89.   {  
  90.       /// <summary>  
  91.       /// 开始打扮  
  92.       /// </summary>  
  93.       public override void ToDressUp()  
  94.       {  
  95.           base.ToDressUp();  
  96.           Console.Write("女友送的围巾 ");  
  97.       }  
  98.   }  
  99.  
  100.   /// <summary>  
  101.   /// 太阳镜装饰类,可以添加需要的装饰类  
  102.   /// </summary>  
  103.   public class Sunglasses :Decorator  
  104.   {  
  105.       /// <summary>  
  106.       /// 开始打扮  
  107.       /// </summary>  
  108.       public override void ToDressUp()  
  109.       {  
  110.           base.ToDressUp();  
  111.           Console.Write("太阳眼镜 ");  
  112.       }  
  113.   }  
     主函数调用如下:
  
  
  1. static void Main(string[] args)  
  2.        {  
  3.            MrLi li = new MrLi();  
  4.  
  5.            //第一天道歉的打扮  
  6.            Console.WriteLine("第一天道歉的打扮:");  
  7.            //道歉信  
  8.            Letters letters = new Letters();  
  9.            //玫瑰花  
  10.            Rose rose = new Rose();  
  11.            //女友送的围巾  
  12.            Scarf scarf = new Scarf();  
  13.  
  14.            //打扮道歉信  
  15.            letters.SetDressUp(li);  
  16.            //打扮玫瑰  
  17.            rose.SetDressUp(letters);  
  18.            //打扮围巾  
  19.            scarf.SetDressUp(rose);  
  20.            //开始打扮  
  21.            scarf.ToDressUp();  
  22.            Console.WriteLine();  
  23.            Console.WriteLine("--------------------------------------");  
  24.            //第二天约会的打扮  
  25.            Console.WriteLine("第二天约会的打扮");  
  26.            //道歉信  
  27.            Letters let = new Letters();  
  28.            //太阳镜  
  29.            Sunglasses sunglasses = new Sunglasses();  
  30.            //女友送的围巾  
  31.            Scarf sca = new Scarf();  
  32.  
  33.            //打扮道歉信  
  34.            let.SetDressUp(li);  
  35.            //打扮玫瑰  
  36.            sunglasses.SetDressUp(let);  
  37.            //打扮围巾  
  38.            sca.SetDressUp(sunglasses);  
  39.            //开始打扮  
  40.            sca.ToDressUp();  
  41.            Console.WriteLine();  
  42.      }  
            运行结果如下:    

    这样利用装饰模式就可以有效的解决将来对新装饰品的扩展而无需去修改原先的类,完全的满足了开放封闭原则。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值