设计模式之三 装饰模式

  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();
      }
复制代码

     运行结果如下:

   

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

 

 

 

 

 

 

 

C#设计模式--装饰模式  

2011-10-14 15:11:53|  分类: C# |  标签: |字号 订阅

 
 


public abstract   class Car
    {
     public abstract void operation();
    }

 public class CreateCar:Car
    {
        public override void operation()
        {
            Console.Write("你用的是小汽车");
        }
    }

装饰类:
 public  abstract  class Dector:Car
    {
       private Car car;

       public void setCompont(Car cars)
       {
           car = cars;
       }
        public override void operation()
        {
            if (car != null)
            {
                car.operation();
            }
        }
    }
、、具体装饰1
public  class MotoCar:Dector
    {

        public override void operation()
        {
            base.operation();
            Console.WriteLine("颜色是黄色的");
        }
    }

装饰2:
 public  class NewCar:Dector
    {
      public override void operation()
      {
          base.operation();
          Console.Write("要高速马达");
      }
    }


客户端:

 Car car = new CreateCar();
            MotoCar motocar = new MotoCar();
            NewCar newcar = new NewCar();
            motocar.setCompont(car);
            newcar.setCompont(motocar);
            newcar.operation();
            Console.ReadKey();
posted @ 2013-03-21 14:41  Star★  阅读(185)  评论(0编辑  收藏  举报