设计模式学习(三): 装饰者模式 (附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)模式.装饰器模式以多客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰器模式的结构 通常给对象添加功能,要么直接修改对象添加相应的功能, ...
随机推荐
- 剑指Offer_5_替换空格
题目描述 请实现一个函数,将一个字符串中的空格替换成"%20". 例如,当字符串为We Are Happy.则经过替换之后的字符串为 We%20Are%20Happy. 在网络编程 ...
- Java-----关于eclipse导入项目发生的问题及解决办法
今天通过eclipse导入了几个项目,项目名出现红叉,对于我这样的强迫症来说是无法容忍的,故现做总结,遇到同学可按照以下方法来操作. 改动的地方主要是两个方面: 1.Tomcat版本问题. 此问题是由 ...
- 转自知乎-wifi破解
上点python有意思的代码. 环境准备 python2.7 pywifi模块 字典 清除系统中的任何wifi连接记录 导入模块 这里用的模块就这三个 pywifi的_wifiutil_linux.p ...
- Android设计模式(九)--外观模式
问题:在Android中,Apk能够有微信,QQ为代表的插件式安装更新功能: 那么问题来了,主系统(姑且这么说)调用插件式安装的子系统.由子系统提供对外的訪问.属不属于一种外观模式呢? 先说设计模式: ...
- 蓝牙核心技术概述(五):蓝牙协议规范(irOBEX、BNEP、AVDTP、AVCTP)
关键词:蓝牙核心技术协议 irDA BNEP AVDTP AVCTP 作者:xubin341719(欢迎转载,请注明作者,请尊重版权,谢谢! )欢迎指正错误,共同学习.共同进步!! 下载链接:Bl ...
- java开发收藏
一.java工具 1.jenkins 项目集成工具 2.launch4j java打包成exe工具 二.json库 1.jsoniter 比以下都快 2.dsljson 3.fastjson 4.gs ...
- AOP入门(转)
本文转自http://www.cnblogs.com/yanbincn/archive/2012/06/01/2530377.html Aspect Oriented Programming 面向切 ...
- 3D位置语音,引领吃鸡游戏体验升级
欢迎大家前往云加社区,获取更多腾讯海量技术实践干货哦~ 作者:腾讯游戏云 导语:在刚刚结束的首届腾讯用户开放日上,腾讯音视频实验室带着3D位置音效解决方案,向所有用户亮相,为用户提供360度立体空间的 ...
- Microsoft Visual Studio 2012旗舰版(VS2012中文版下载)官方中文版
Microsoft Visual Studio 2012 Ultimate旗舰版(VS2012中文版下载)是一个最先进的开发解决方案,它使各种规模的团队能够设计和创建出使用户欣喜的引人注目的应用程序. ...
- n年前,我没钱但年轻,我怕n年后我老时,还是一无所成——2017我的收获和反思
记得当年我刚从学校里出来时,应该和现在的95后差不多,当时还是很惶恐的,怕找不到工作,怕无法挣到足够的钱买房子支撑家庭,(当然还有其它的担心点),却唯独没意识到自己拥有着最宝贵的财富:年轻. 年轻意味 ...