设计模式学习(三): 装饰者模式 (附C#实现)

时间:2022-04-29
本文章向大家介绍设计模式学习(三): 装饰者模式 (附C#实现),主要内容包括需求、初版设计、再版设计、设计原则、使用装饰者模式、装饰者模式定义、重新设计、C#代码实现、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。

需求

做一个咖啡店的订单系统。

买咖啡时,可以要求加入各种调料,如奶,豆浆,摩卡等。咖啡店会根据调料的不同收取不同的费用。订单系统要考虑这些。

初版设计

然后下面就是所有的咖啡....:

cost方法将计算出咖啡加上各种调料后的价格。

这种方法太笨了。。。必须换一种。

再版设计

使用实例变量和继承!

但是有新的问题:

1.调料价格变化就需要更改现有的代码。

2.一旦出现新的调料,就需要加上新的方法,并改变超类中的cost方法。

3.如果有新的饮料,有些调料可能会不适用。

4.想买双倍的摩卡咖啡怎么办?

设计原则

类应该对扩展开发,对修改关闭。

使用装饰者模式

装饰者模式定义

装饰者模式动态的将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

重新设计

C#代码实现

Beverage:

namespace C03DecoratorPattern.Bases
{
    public abstract class Beverage
    {
        protected string Description;

        protected Beverage()
        {
            Description = "Unknown Beverage";
        }

        public abstract double Cost();

        public virtual string GetDescription()
        {
            return Description;
        }
    }
}

CondimentDecorator:

namespace C03DecoratorPattern.Bases
{
    public abstract class CondimentDecorator : Beverage
    {
        public abstract override double Cost();
        public abstract override string GetDescription();
    }
}

咖啡们:

namespace C03DecoratorPattern.Beverages
{
    public class Espresso : Beverage
    {
        public Espresso()
        {
            Description = "Espresso";
        }

        public override double Cost()
        {
            return 1.99;
        }
    }
}

namespace C03DecoratorPattern.Beverages
{
    public class HouseBlend : Beverage
    {
        public HouseBlend()
        {
            Description = "House Blend Coffee";
        }

        public override double Cost()
        {
            return .89;
        }
    }
}

调料们:

namespace C03DecoratorPattern.Condiments
{
    public class Milk : CondimentDecorator
    {
        private readonly Beverage _beverage;

        public Milk(Beverage beverage)
        {
            _beverage = beverage;
        }

        public override double Cost()
        {
            return .34 + _beverage.Cost();
        }

        public override string GetDescription()
        {
            return $"{_beverage.GetDescription()}, Milk";
        }
    }
}

namespace C03DecoratorPattern.Condiments
{
    public class Mocha : CondimentDecorator
    {
        private readonly Beverage _beverage;

        public Mocha(Beverage beverage)
        {
            _beverage = beverage;
        }
        public override double Cost()
        {
            return .2 + _beverage.Cost();
        }

        public override string GetDescription()
        {
            return $"{_beverage.GetDescription()}, Mocha";
        }
    }
}

namespace C03DecoratorPattern.Condiments
{
    public class Soy: CondimentDecorator
    {
        private readonly Beverage _beverage;

        public Soy(Beverage beverage)
        {
            _beverage = beverage;
        }

        public override double Cost()
        {
            return .17 + _beverage.Cost();
        }

        public override string GetDescription()
        {
            return $"{_beverage.GetDescription()}, Soy";
        }
    }
}

测试程序:

namespace C03DecoratorPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            Beverage beverage = new Espresso();
            Console.WriteLine($"{beverage.GetDescription()} $ {beverage.Cost()}");

            Beverage beverage2 = new HouseBlend();
            beverage2 = new Mocha(beverage2);
            beverage2 = new Milk(beverage2);
            beverage2 = new Soy(beverage2);
            Console.WriteLine($"{beverage2.GetDescription()} $ {beverage2.Cost()}");

            Console.ReadLine();
        }
    }
}

运行结果: