博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
装饰者模式--Head First设计模式【笔记】
阅读量:6434 次
发布时间:2019-06-23

本文共 4071 字,大约阅读时间需要 13 分钟。

星巴克:世界闻名的咖啡连锁店。他的订单系统,如果你有兴趣了解下的话,跟我来吧。

一、他们原先的设计

//Beverage(饮料)是一个抽象类,店里所提供的饮料都必须继承此类。 public abstract  class Beverage    {       public   string description = "Unknown Beverage"; //description(描述),店里面所有饮料的描述。       public  string getDescription() //获取饮料描述        {            return description;        }        public abstract double cost();//价格,由子类自己实现。    }

HouseBlend(家常咖啡):星巴克首选咖啡。

public  class HouseBlend:Beverage     {        public HouseBlend()         {            description = "House Blend Coffee";        }        public override double cost()        {            return 0.89;        }    }

Espresso(特浓咖啡)素有“咖啡之魂”的美称。对于咖啡馆来说,“没卖 ‘Espresso’ 的咖啡馆就不是咖啡馆”,可见 “Espresso“ 重要性。

public  class Espresso:Beverage     {        public Espresso()         {            description = "Espresso";        }        public override double cost()        {            return 1.99;        }    }

现在市场需求出现新的变化:我要红豆特浓咖啡(特浓咖啡+红豆)

加个新类HongDouEspresso 如下?那么如果我换个口味(即新的配料+特浓咖啡)要豆浆特浓咖啡(豆浆+特浓咖啡),那不是又要新建一个类?如果我一天换个口味,那么这个系统存在的每一天不是都要升级一次?这是多么恐怖且二逼的系统啊!!!!

那么,有没有办法把这些配料“动态地”加到咖啡里面来,而不是像下面的代码那样写死在代码中。

public  class HongDouEspresso:Beverage     {        public Espresso()         {            description = "HongDouEspresso";        }        public override double cost()        {            return 2.29;        }    }

再想想我们OO设计原则

1.找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
2.针对接口编程,而不是针对实现编程。
3.多用组合,少用继承。
4.为了交互对象之间的松耦合设计而努力。
5.类应该对扩展开发,对修改关闭。

二、星巴克订单系统二代出来了:装饰者模式

1  public abstract  class Beverage//饮料的抽象类,即组件的抽象类2     {3        public   string description = "Unknown Beverage";4         public virtual  string getDescription() //用虚方法,因为我想要把后面加进来的配料名称也显示出来。5         {6             return description;7         }8         public abstract double cost();9     }

5.类应该对扩展开发,对修改关闭。所以特浓咖啡,家常咖啡的类代码不变。如下

//特浓咖啡 public  class Espresso:Beverage     {        public Espresso()         {            description = "Espresso";        }        public override double cost()        {            return 1.99;        }    }
//家常咖啡public  class HouseBlend:Beverage     {        public HouseBlend()         {            description = "House Blend Coffee";        }        public override double cost()        {            return 0.89;        }    }

神奇的配料代码来了

//配料的抽象类  public abstract  class CondimentDecorator:Beverage     {             //每个配料都要实现的抽象类,继承Beverage 是为了保存对某个Beverage 对象的引用,实现多态的“类型匹配”。    }

 

//红豆(HongDou配料的实现代码) public  class HongDou:CondimentDecorator    {       Beverage beverage;//用实例变量来记录饮料(“这些配料“动态地”加到咖啡里面来,而不是像下面的代码那样写死在代码中。”关键实现)        //把饮料当做构造函数参数,是为了把饮料记录到实例变量中。(“这些配料“动态地”加到咖啡里面来,而不是像下面的代码那样写死在代码中。”关键实现) public HongDou(Beverage beverage)       {           this.beverage = beverage;       }        public override string getDescription()        {            return beverage.getDescription() + ",HongDou";//我们希望不仅记录饮料,还记录配料。        }        public override double cost()        {
//要计算带HongDou配料的饮料价格,首先把调用委托给被装饰对象(组件),以计算价格,如何加上HongDou价格,得到最终价格。 return 0.35 + beverage.cost(); } }

 

//豆浆(DouJiang)的代码跟红豆(HongDou) 代码类似,就不多做阐述了。public  class DouJiang:CondimentDecorator     {       Beverage beverage;       public DouJiang(Beverage beverage)       {           this.beverage = beverage;       }        public override string getDescription()        {            return beverage.getDescription() + ",DouJiang";        }        public override double cost()        {            return 0.20 + beverage.cost();        }    }

重要时刻:调试下--小二,给爷上一大杯 红豆双豆浆家常咖啡!

static void Main(string[] args)        {                        Beverage beverage2 = new HouseBlend();//创建一个组件对象--家常咖啡            beverage2 = new DouJiang(beverage2);//豆浆装饰            beverage2 = new DouJiang(beverage2);            beverage2 = new HongDou(beverage2);//红豆装饰            Console.WriteLine(beverage2.getDescription() + "     " + "$" + beverage2.cost());            Console.ReadKey();        }

小二:来了,大爷1.64美刀。

到这来星巴克的订单系统之装饰者模式基本是说完了。

突然,大爷冒出来说:小二,我买这么多,你也不给我打个折什么的啊?至少豆浆给我打个七五折吧?

我们装饰者模式不是万能的,遇到这种情况就不好解决。那怎么办?咱们先回去想想!!!

转载于:https://www.cnblogs.com/Techlink/archive/2012/08/27/2658289.html

你可能感兴趣的文章
监控webservice信息
查看>>
a标签中href=""的几种用法(转)
查看>>
python
查看>>
ubuntu 常用生产环境部署配置测试调优
查看>>
【JS】//将中文逗号转换为英文逗号
查看>>
在VS2012中实现Ext JS的智能提示太简单了
查看>>
Extnet Direct 提交后台事件文件下载设置
查看>>
邻接矩阵与二叉排序树
查看>>
CSS选择器
查看>>
购物车练习
查看>>
js实现在表格中删除和添加一行
查看>>
SOCKET简单爬虫实现代码和使用方法
查看>>
跨域解决方案汇总
查看>>
In App Purchase
查看>>
js判断对象的类型的四种方式
查看>>
RPC框架的可靠性设计
查看>>
使用自选择创建团队
查看>>
基准测试(Benchmarks)不必消亡
查看>>
ceph 常用命令记录(完善中...)
查看>>
C# 7.3新特性一览
查看>>