顾客可以需要任何种类的咖啡,我们可以根据Range的范围来调节。你可能会说,且慢,如果我只需要咖啡加奶,怎么办?
这就要麻烦一点:
def c = new Coffee()
def m = new Milk()
m.types = ['Coffee','Milk']
(c..m).each{
println it.description()
}
麻烦在于我们不能使用"Base"类默认的"types"的值了,需要自定义"types"的值,如:
m.types = ['Coffe','Milk']
运行结果为:
Coffee
with milk
到了这里,你可能还会说,且慢,Decorate模式拥有良好的扩展性,你使用自定义Range类实现的咖啡系列也有良好的扩展性吗?
我们说,当然,自定义Range类实现的咖啡系列依然有着良好的扩展性。我们来看看实例吧。
比如,我们想在上面例子的基础上增加一个咖啡类型:巧克力咖啡。我们就可以直接增加下面的类:
package range;
class Chocolate extends Base{
def Chocolate()
{
this.type = 'Chocolate'
this.getIndex()
}
def description()
{
'with chocolate'
}
def price()
{
8
}
}
这都很简单,没有什么特别的。现在,我们就可以使用巧克力咖啡了:
def coffee = new Coffee()
def chocolate = new Chocolate()
chocolate.types = ['Coffee','Ice','Milk','Sugar','Chocolate']
(coffee..chocolate).each{
println it.description()
}
运行结果为:
Coffee
with ice
with milk
with sugar
with chocolate
到现在为止,Decorate模式所有的功能我们使用自定义Range类一一实现,我们可以这样说,使用自定义的Range类能够替代Decorate模式。
你可能会说,仅仅是替代而已,但使用自定义的Range类来实现该功能似乎比Decorate模式更为麻烦,至少要比Decorate模式多写一个自定义的Range类,如上面的"Base"类。这样的话,我在实际编码的过程中,是不大会使用自定义的Range类的。
但实际情况是,使用自定义的Range类实现的咖啡系列比起使用Decorate模式实现的咖啡系列业务上更为灵活,因此比Decorate模式更为好用,特别是在业务比较复杂多变的情况下。
例如,我们需要实现某一个顾客他买了什么样的咖啡,以及他总的花费,就可以如下编码:
def des1 = ''
def total = 0
(coffee..sugar).each{
des1 += it.description()+' '
total += it.price()
}
println "Your need: ${des1}"
println "Your charge: ${total}"
运行结果为:
Your need: Coffee with ice with milk with sugar
Your charge: 19
再如,我们需要知道某一个顾客他的花费的详细清单以及总的花费,就可以这样编码了,如下:
def des2 = ''
def total2 = 0
(coffee..sugar).each{
des2 += it.description()+' : '+it.price()+'\n'
total2 += it.price()
}
println "Your charge \n${des2}"
println "Your total charge: ${total2}"
运行结果为:
Your charge
Coffee : 10
with ice : 1
with milk : 5
with sugar : 3
Your total charge: 19
到现在为止,我们总共为咖啡系列写了三个逻辑:首先是需要知道顾客买了什么样的咖啡,以便工作人员好加以配置;然后,我们的收银人员需要知道顾客总共的花费;最后,我们的顾客则需要知道他的各个细项的开销以及总的花费。
这些逻辑如果是使用Decorate模式来实现的话,我们需要为每一个咖啡系列的类实现三个独立的方法来完成。
但是,如果我们使用自定义的Range类来实现的话,我们只需要为每一个咖啡系列的类实现两个基本的方法即可。
想想看,如果业务逻辑更为复杂,那又会怎么样呢?
现在,使用自定义的Range类来实现的咖啡系列是不是已经让我们更为激动了。最后,我们来做一个小结吧!
使用Decorate模式实现的咖啡系列似乎更为怪异,它需要把很多客户端要使用到的逻辑集成到各个咖啡系列的类中去,这不符合面向对象设计的基本原则--类的功能要单一。我们的咖啡系列的类其实只有两个简单的功能:即各自的描述和价格。
使用Decorate模式实现的咖啡系列正因为把很多客户端要使用到的逻辑集成到了各个类中去,使得我们的咖啡系列就难以扩展。比如,我们的客户端需要增加功能,我们就不得不辛辛苦苦的到咖啡系列的各个类中去增加各自的方法。这种扩展性其实已经是一个很大的局限性了。
而使用自定义Range类实现的咖啡系列则把这种复杂的业务交给了客户端自己处理,我们咖啡系列的各个类只需要实现最基本的功能,即:各自的描述和价格。这样,我们的咖啡系列就更加容易扩展了。