代码改变世界

结合项目实例 回顾传统设计模式(三)装饰者模式

2011-10-02 15:09  熬夜的虫子  阅读(730)  评论(1编辑  收藏  举报

说到这个模式的项目实例 虫子也满头疼的 所谓装饰者模式说白了动态将职责附加到对象上。如果你在项目某个场景中需要功能扩展根据基类衍生出非常多的子类,那么装饰者模式无疑是很好的。不过其实在实际的项目中,往往大家不直接衍生子类,而是通过组合的方式,根据逻辑讲各种扩展叠加来,对外公布的只是一个标签一个壳而已。

所以这个章节,虫子就虚构一个实例了。还拿电商来说、点券赠品系统。

背景:

1.所有点券、优惠券、赠品券、积分继承同一个基类 基类券

2.不用种类的券可以混合搭配

3.积分根据不同的场景可以配置不同的规则

4.升级礼券在上层礼券基础上添加

一般情况下 大家可以就这样设计了

/// <summary>
    
/// 基卡
    
/// </summary>
    public abstract class BaseCard
    {      
        public string decription;
        public abstract double cost();
       
    }

    /// <summary>
    
/// 点卡A
    
/// </summary>
    public class cardA : BaseCard
    {
        public cardA()
        {
            decription = "cardA";
        }
        public override double cost()
        {
            return 50.00;
        }
    }

    /// <summary>
    
/// 优惠券A
    
/// </summary>
    public class couponsA : BaseCard
    {
        public couponsA()
        {
            decription = "couponsA";
        }
        public override double cost()
        {
            return 40.00;
        }
    }

    /// <summary>
    
/// 优惠券B
    
/// </summary>
    public class couponsB : BaseCard
    {
        public couponsB()
        {
            decription = "couponsB";
        }
        public override double cost()
        {         
            return 30.00;
        }
    }

    /// <summary>
    
/// 国庆礼券
    
/// </summary>
    public class GQCard : BaseCard
    {
        cardA a = new cardA();
        couponsA ca = new couponsA();
        public GQCard()
        {
            decription = "GQCard";
        }
        public override double cost()
        {
            return a.cost() + ca.cost();
        }
    }

    /// <summary>
    
/// 国庆升级A等礼券
    
/// </summary>
    public class GQACard : BaseCard
    {
        cardA a = new cardA();
        couponsA ca = new couponsA();
        couponsB cb = new couponsB();
        public GQACard()
        {
            decription = "GQACard";
        }
        public override double cost()
        {
            return a.cost() +ca.cost()+ cb.cost();
        }
    }

 

设计模式的原则是类应该对扩展开放对修改关闭,而上述设计在礼券升级种类越来越多的情况下并且现有的礼券已经频繁更新的话 对于庞大的礼券系统肯定是不理想的

那么我们换个思路

 

/// <summary>
    
/// 基卡
    
/// </summary>
    public abstract class BaseCard
    {      
        public string decription;
        public abstract double cost();
       
    }

    /// <summary>
    
/// 点卡A
    
/// </summary>
    public class cardA : baseoupons
    {
        BaseCard basec;
        public cardA(BaseCard basec)
        {
            this.basec = basec;
            decription = "cardA," + basec.decription;
        }
        public override double cost()
        {
            return 50.00 + basec.cost(); 
        }
    }

    /// <summary>
    
/// 优惠券A
    
/// </summary>
    public class couponsA : baseoupons
    {
        BaseCard basec;
        public couponsA(BaseCard basec)
        {
            this.basec = basec;
            decription = "couponsA," + basec.decription;
        }
        public override double cost()
        {
            return 40.00 + basec.cost();
        }
    }

    /// <summary>
    
/// 优惠券B
    
/// </summary>
    public class couponsB : baseoupons
    {
        BaseCard basec;
        public couponsB(BaseCard basec)
        {
            this.basec = basec;
            decription = "couponsB," + basec.decription;
        }
        public override double cost()
        {
            return 30.00 + basec.cost(); 
        }
    }

    /// <summary>
    
/// 基类礼券
    
/// </summary>
    public class baseoupons : BaseCard
    {
        BaseCard basec;
        public baseoupons(BaseCard basec)
        {
            this.basec = basec;
            decription = basec.decription;
        }
        public baseoupons()
        {
            
        }
        public override double cost()
        {
            if (basec != null)
            {
                return basec.cost();
            }
            else
            {
                return 0;
            }
        }
      
    }

 

 让我们看看装饰者模式的强大

 

  BaseCard a = new baseoupons();
            a = new cardA(a);
            a = new couponsA(a);
            a = new couponsB(a);

            Console.WriteLine("国庆礼券由"+a.decription+"组成");
            Console.WriteLine(a.cost().ToString());

            BaseCard b = new cardA(a);
           
            Console.WriteLine("国庆升级礼券由" + b.decription + "组成");
            Console.WriteLine(b.cost().ToString());
            Console.ReadLine();

 

总结:继承属于扩展形式之一,但不见得是达到弹性设计的最佳方式,在我们的设计当中应该允许行为可以被扩展,而无需修改现有的代码。就如上述的例子装饰者模式也可以让我们扩展行为。不过装饰者模式也有缺点,它会导致设计中出现许多小对象,如果过度使用,会让程序变得很复杂。