需求

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

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

初版设计

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

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()
        {
            ;
        }
    }
}

调料们:

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

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

        public override double Cost()
        {
             + _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()
        {
             + _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()
        {
             + _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();
        }
    }
}

运行结果:

设计模式学习(三): 装饰者模式 (附C#实现)的更多相关文章

  1. 设计模式学习之装饰者模式(Decorator,结构型模式)(16)

    参考地址:http://www.cnblogs.com/zhili/p/DecoratorPattern.html 一.定义:装饰者模式以对客户透明的方式动态地给一个对象附加上更多的责任,装饰者模式相 ...

  2. 设计模式学习心得<装饰器模式 Decorator>

    装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰类,用来包装 ...

  3. Java-马士兵设计模式学习笔记-装饰者模式

    Java装饰者模式简介 一.假设有一个Worker接口,它有一个doSomething方法,Plumber和Carpenter都实现了Worker接口,代码及关系如下: 1.Worker.java p ...

  4. C#设计模式学习之装饰者模式

    写这个随笔时,其实对该模式理解的并不是十分透彻.在此想到什么写什么,希望对自己对他人有所帮助. 装饰者模式主要是应用继承和组合的思想,极大的实现了程序的多态,使得的程序有了更高的扩展性. 第一个基础例 ...

  5. Javascript设计模式学习三(策略模式)

    定义:定义一系列的算法,把它们一个个封装起来,并且使它们可以互相替换.目的:将算法的使用和算法的实现分离开来.比如: if(input == 'A'){ return 1; } if(input == ...

  6. 设计模式学习系列6 原型模式(prototype)

    原型模式(prototype)用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象.允许一个对象再创建另外一个新对象的时候根本无需知道任何创建细节,只需要请求圆形对象的copy函数皆可. 1 ...

  7. JAVA设计模式之【装饰者模式】

    JAVA设计模式之[装饰者模式] 装饰模式 对新房进行装修并没有改变房屋的本质,但它可以让房子变得更漂亮.更温馨.更实用. 在软件设计中,对已有对象(新房)的功能进行扩展(装修). 把通用功能封装在装 ...

  8. 重学 Java 设计模式:实战装饰器模式(SSO单点登录功能扩展,增加拦截用户访问方法范围场景)

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 对于代码你有编程感觉吗 很多人写代码往往是没有编程感觉的,也就是除了可以把功能按照固 ...

  9. Java设计模式12:装饰器模式

    装饰器模式 装饰器模式又称为包装(Wrapper)模式.装饰器模式以多客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰器模式的结构 通常给对象添加功能,要么直接修改对象添加相应的功能, ...

随机推荐

  1. NBUT 1217 Dinner

    [1217] Dinner 时间限制: 1000 ms 内存限制: 32768 K 问题描写叙述 Little A is one member of ACM team. He had just won ...

  2. Matlab 2014b For Mac安装破解

    1.Matlab 2014b 的安装和破解文件下载: 安装文件:http://www.cncrk.com/downinfo/80718.html 破解文件:http://pan.baidu.com/s ...

  3. dotnetcore 自动迁移工具

    费心思做了一个简单的dotnetcore迁移工具,欢迎大家使用和交流 工具所做的工作: 查找所有输入目录的子目录和上级目录,获取包含*.sln的项目集合,可批量迁移. 替换*.sln文件中的*.csp ...

  4. Asp.net mvc 知多少(二)

    本系列主要翻译自<ASP.NET MVC Interview Questions and Answers >- By Shailendra Chauhan,想看英文原版的可访问http:/ ...

  5. Java方法的概念及使用

    方法 将一段逻辑或者功能提取出来,这种提取的形式就是函数 格式 修饰符 返回值类型 函数名(参数列表){ 方法体: return 返回值; } //明确返回值类型---求两个整数的和,确定结果一定是整 ...

  6. Elasticsearch全文搜索——adout

    现在尝试下稍微高级点儿的全文搜索——一项传统数据库确实很难搞定的任务. 搜索下所有喜欢攀岩(rock climbing)的雇员: curl -XGET 'localhost:9200/megacorp ...

  7. springboot 热部署 idea版本(转)

    spring为开发者提供了一个名为spring-boot-devtools的模块来使Spring Boot应用支持热部署,提高开发者的开发效率,无需手动重启Spring Boot应用. devtool ...

  8. 企业级nosql数据库应用与实战-redis

    一.NoSQL简介 1.1 常见的优化思路和方向 1.1.1 MySQL主从读写分离 由于数据库的写入压力增加,Memcached只能缓解数据库的读取压力.读写集中在一个数据库上让数据库不堪重负,大部 ...

  9. Android开发之常见事件响应方式

    常见的事件有   (1)单击事件 onClickListener (2)长按事件 onLongClickListener (3)滑动事件 onTouchListener (4)键盘事件 onKeyLi ...

  10. 【JS】数据类型

    其他类型转化为boolean类型规则: number:非0为true,0和NaN为false: String:非空为true,空为false: Object:任何对象都为true 任何变量赋值为nul ...