设计模式学习(三): 装饰者模式 (附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() { ; } } }
调料们:
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#实现)的更多相关文章
- 设计模式学习之装饰者模式(Decorator,结构型模式)(16)
参考地址:http://www.cnblogs.com/zhili/p/DecoratorPattern.html 一.定义:装饰者模式以对客户透明的方式动态地给一个对象附加上更多的责任,装饰者模式相 ...
- 设计模式学习心得<装饰器模式 Decorator>
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰类,用来包装 ...
- Java-马士兵设计模式学习笔记-装饰者模式
Java装饰者模式简介 一.假设有一个Worker接口,它有一个doSomething方法,Plumber和Carpenter都实现了Worker接口,代码及关系如下: 1.Worker.java p ...
- C#设计模式学习之装饰者模式
写这个随笔时,其实对该模式理解的并不是十分透彻.在此想到什么写什么,希望对自己对他人有所帮助. 装饰者模式主要是应用继承和组合的思想,极大的实现了程序的多态,使得的程序有了更高的扩展性. 第一个基础例 ...
- Javascript设计模式学习三(策略模式)
定义:定义一系列的算法,把它们一个个封装起来,并且使它们可以互相替换.目的:将算法的使用和算法的实现分离开来.比如: if(input == 'A'){ return 1; } if(input == ...
- 设计模式学习系列6 原型模式(prototype)
原型模式(prototype)用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象.允许一个对象再创建另外一个新对象的时候根本无需知道任何创建细节,只需要请求圆形对象的copy函数皆可. 1 ...
- JAVA设计模式之【装饰者模式】
JAVA设计模式之[装饰者模式] 装饰模式 对新房进行装修并没有改变房屋的本质,但它可以让房子变得更漂亮.更温馨.更实用. 在软件设计中,对已有对象(新房)的功能进行扩展(装修). 把通用功能封装在装 ...
- 重学 Java 设计模式:实战装饰器模式(SSO单点登录功能扩展,增加拦截用户访问方法范围场景)
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 对于代码你有编程感觉吗 很多人写代码往往是没有编程感觉的,也就是除了可以把功能按照固 ...
- Java设计模式12:装饰器模式
装饰器模式 装饰器模式又称为包装(Wrapper)模式.装饰器模式以多客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰器模式的结构 通常给对象添加功能,要么直接修改对象添加相应的功能, ...
随机推荐
- hadoop多文件格式输入
版本号: CDH5.0.0 (hdfs:2.3.mapreduce:2.3,yarn:2.3) hadoop多文件格式输入,一般能够使用MultipleInputs类指定不同的输入文件路径以及输入文件 ...
- ListView与Adapter笔记:ZrcListView
怕自己说的不清不楚,先来一个郭神的文章镇楼:http://blog.csdn.net/guolin_blog/article/details/44996879 github:https://githu ...
- hdu1570(排列和组合公式的应用)
题意: 给出字符A.则求全排列 A(n,m)=n!/(n-m)! 给出字符C.则求全组合 C(n,m)=n!/(m!*(n-m)!) http://acm.hdu.edu.cn/showproblem ...
- [基础规范]JavaBeans规范
本文来自维基百科:http://en.wikipedia.org/wiki/JavaBeans#JavaBean_conventions JavaBeans是Java语言中能够反复使用的软件组件,它们 ...
- 大数据学习(8)Hive基础
什么是Hive Hive是一个基于HDFS的查询引擎.我们日常中的需求如果都自己去写MapReduce来实现的话会很费劲的,Hive把日常用到的MapReduce功能,比如排序.分组等功能进行了抽象, ...
- Struts配置详解
一.Stuts的元素 1 web.xml 任何一个web应用程序都是基于请求响应模式进行构建的,所以无论采用哪种MVC框架,都离不开web.xml文件的配置.换句话说,web.xml并不是Struts ...
- linux下用split命令将一个大的文件拆分成若干小文件
命令 split -l 50 wlan_date.txt wlan 说明:按50行给文件进行拆分,如果没有最后面的参数,命名将会是xaa,xab等.
- 【python】字符串
>>> str1="welcom to China">>> str1[2:4]'lc'>>> str1[7]'t'>&g ...
- windos10安装mongodb并配置
想了想还是把这个写上吧,毕竟网上的教程有不少坑的. 首先下载mongodb,如果你嫌官网慢,那么你可以去我的百度云下载 链接:http://pan.baidu.com/s/1pKEWTBX 密码:v3 ...
- ES6之Set方法与Map方法
ES6提供了新的数据结构--Set与Map,Set本身是一个构造函数且成员的值是唯一的,没有重复的值!!!Set()是一个存储已排序的无重复元素的数据而Map()是一对数据Map()使用关键值Key来 ...