设计模式(九)装饰模式(Decorator)

一、咖啡店的故事

这次我们借用HeadFirst中的咖啡店的故事来讨论一下装饰模式。咖啡店中有各种种类的咖啡和咖啡需要加的配料。有一家咖啡店为了提高效率打算开发一套咖啡订购系统,用户可以根据清单选择咖啡和咖啡所加的配料,系统可以自动的计算总价格。

第一种方案是这个样子的:

这里写图片描述

Beverge是一个抽象类,店内所有的饮料都必须继承自这个类。description用来描述这个是什么类型的饮料例如:Dark Roast。getDescription()方法返回这种饮料的描述,cost()返回这种饮料的描述,但是cost()方法是抽象的,具体的实现由子类决定,因为每中不同饮料价格都不相同。下面的四个类代表四种不同的饮料,他们都实现了父类的cost方法。

因为用户购买咖啡时还需要搭配一些调料,所以每种咖啡又分为各种不同的种类,于是系统就变成了这个样子。

这种方案造成的最大的问题就是类的数量众多,维护成本非常大。试想如果牛奶的价格上涨,那么每种添加牛奶的咖啡就都必须修改自己的价格,所以这种方案不符合“开-闭”原则。

第二种方案:

milk,soy,mocha,whip都是代表有没有这种调料的布尔值,下面的hasMilk()方法等是返回这个变量的值,setMilk()方法是设置这个变量的值。并且Beverage中的cost()方法也不再是抽象方法而是返回所加的各种调料的价格,子类会覆盖这个cost方法,子类的cost方法会返回总的价格,首先调用父类的cost方法得到调料的价格,然后再加上咖啡的价格,返回总的价格。

采用这种方法只需要5各类就能表示出这家咖啡店中所有的咖啡和配料组合。但是仍然存在问题,试想,如果我们如果增加了一种新的调料,那么Beverage类不就需要更改吗,如果客户想买双倍摩卡咖啡怎么办?如果以后开发出了一种新的饮料,比如说“茶”,对于这种饮料而言某些调料是不合适的,比如说(奶泡),但是它还是继承了所有的方法,包括不合适的。

第三种方案:装饰模式

我们把咖啡本身当做是主要的本体,而把奶泡等调料当做是咖啡的装饰,我们通过给本体添加不同的装饰来获得不同的结果。

这是咖啡的本体,我们以DarkRoast为例,这种咖啡是继承自Beverage的,它的cost()是用来返回咖啡的价格。

如果客户想要摩卡咖啡,就建立一个Mocha对象,并用他将DarkRoast对象包起来(装饰)。Mocha就是一个装饰者,他的类型和他所装饰的类型是一样的,都是Beverage。Mocha也有一个cost方法,它的cost()方法会首先调用所装饰的对象DarkRoast类的cost

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值