按:本文原文转载bjdp.org的热心匠友刘成章为2013年12月1日的编码操练活动操练Decorator设计模式所编写的编码招式。有关这个题材的招式,我曾在2004年出版的Head First Design Patterns一书中见过,书中将该招式命名为Starbuzz Coffee,故本人将此招式命名为Kata Starbuzz Coffee。在此对成章匠友和Head First Design Patterns一书作者表示感谢。
咖啡连锁店KataStarbuzzCoffee招式-刘成章版
一、背景介绍:
设想一家咖啡连锁店需要给顾客提供各种饮料,通常每种饮料还需要配上不同的调味品。当然,不同的顾客对调味品的要求也是不同的,有些顾客可能喜欢原味;有些喜欢巧克力味;有些喜欢柠檬味;有些喜欢摩卡味……,等等。点单系统需要一个“返回顾客所点的饮料和调味品的名目说明及总价格”的功能。请实现之。
二、需求说明:
饮料(Beverage)价目表:
序号 |
饮料名称 |
描述 |
价格 |
备注 |
1 |
咖啡 |
Coffee |
22.00 |
|
2 |
清/红/绿茶
|
PlainTea BlackTea GreenTea |
25.00 |
|
3 |
鲜啤 |
Beer |
18.00 |
|
4 |
可乐 |
Coke |
12.00 |
|
调味品(Condiment)价目表:
序号 |
调味品名称 |
描述 |
价格 |
备注 |
1 |
糖 |
Sugar |
免费 |
|
2 |
牛奶 |
Milk |
3.50 |
|
3 |
蜂蜜 |
Honey |
4.50 |
|
4 |
柠檬 |
Lemon |
5.00 |
|
5 |
巧克力 |
Chocolate |
7.00 |
|
6 |
摩卡 |
Mocha |
8.00 |
|
说明:1)店老板注重专而精,目前就这4种饮料和6种调味品,但不排除日后会增加或淘汰某一种饮料或调味品品种;
2)调味品不单卖。
三、招式说明:
1、不一定非得要用Decorator模式,我们的目标是实现功能需求,代码简洁。因此只要能实现功能需求,并保持好的代码质量,遵循开-闭原则,用任何一种模式都可以。例如,Composite组合模式或许也是一个不错的选择(伍斌_Ben注:Composite模式是否是实现该招式的最佳模式值得商榷,因为根据四巨头关于Composite模式的意图的描述,Composite模式更适合于表达整体与部分之关系的树形层级结构,而次招式中多个调味品与饮料之间的层级关系并不明显。)。
2、当然,该招式是在Decorator模式指引下编写的(还未写代码验证),所以用Decorator模式应该可以实现功能,并很好的遵循开-闭原则。如果把后面的需求变化也做完,可能会用到TemplateMethod模式。
3、第一次编写测试用例,未考虑周全和冗余,因此下面的测试用例如果有不当之处,请及时联系以便我们更正。另外,我编写这组测试用例的一个主要目的是帮助大家理解需求,也可以用于TDD。当然,如果已经很好的理解需求了,完全可以自己编写自己需要的测试用例。
4、如果觉得招式有点复杂,可以只实现前三组测试用例,即不考虑需求变化导致的改动。
5、该招式改编自网上的一个例子,具体链接已经找不到了。若有发现,请告诉我们,我将及时引用。我在学习Decorator模式时看到过,感觉不错,它帮助我理解了Decorator模式。
四、测试用例:
第一组测试用例:
1. 顾客购买一杯咖啡(Coffee):
点单系统打印出(即小票上要显示的文本):Coffee (22.00) | Total=22.00
2. 顾客购买一杯清茶(PlainTea):
点单系统打印出(即小票上要显示的文本):PlainTea(25.00) | Total=25.00
3. 顾客购买一杯啤酒(Beer):
点单系统打印出(即小票上要显示的文本):Beer (18.00) | Total=18.00
4. 顾客购买一杯可乐(Coke):
点单系统打印出(即小票上要显示的文本):Coke (12.00) | Total=12.00
第二组测试用例:
5. 顾客购买一杯咖啡(Coffee)外加一份牛奶(Milk):
点单系统打印出(即小票上要显示的文本):Coffee (22.00) + Milk (3.50)| Total=25.50
6. 顾客购买一杯红茶(BlackTea)外加一份蜂蜜(Honey):
点单系统打印出(即小票上要显示的文本):BlackTea(25.00) + Honey (4.50)| Total=29.50
7. 顾客购买一杯鲜啤(Beer)外加一份柠檬(Lemon):
点单系统打印出(即小票上要显示的文本):Beer (18.00) + Lemon (5.0)| Total=23.00
8. 顾客购买一杯可乐(Coke)外加一份柠檬(Lemon):
点单系统打印出(即小票上要显示的文本):Coke (12.00) + Lemon (5.0)| Total=17.00
第三组测试用例:
9. 顾客购买一杯咖啡(Coffee),另加一份蜂蜜和一份牛奶:
点单系统打印出(即小票上要显示的文本):Coffee (22.00) + Honey (4.50) + Milk (3.50)| Total=30.00
10. 顾客购买一杯绿茶(GreenTea),另加一份蜂蜜、一份牛奶和一份巧克力:
点单系统打印出(即小票上要显示的文本):GreenTea (22.00) + Honey (4.50) + Milk (3.50)+ Chocolate (7.00) | Total=37.00
11. 顾客(一个调皮的小孩)购买一杯可乐(Coke),另加所有的调味品各来一份:
点单系统打印出(即小票上要显示的文本):Coke (12.00) + Milk (3.50) + Honey (4.50) + Lemon(5.0) + Chocolate (7.00) + Mocha (8.0) | Total=40.00
第四组测试用例(需求变化1):
现在新增了一种饮料,叫心痛的感觉,价格为49.00
饮料(Beverage)价目表*:
序号 |
饮料名称 |
描述 |
价格 |
备注 |
1 |
咖啡 |
Coffee |
22.00 |
|
2 |
茶 |
PlainTea BlackTea GreenTea |
25.00 |
|
3 |
鲜啤 |
Beer |
18.00 |
|
4 |
可乐 |
Coke |
12.00 |
|
5 |
心痛的感觉 |
LoveFeelings |
49.00 |
新品 |
… |
… |
|
|
|
如果顾客选择了新品,那么再购买调味品可以享受80%的折扣。
12. 顾客购买一杯心痛的感觉(LoveFeelings),他想体验原汁原味的味道,没有购买调味品:
点单系统打印出(即小票上要显示的文本):LoveFeelings (49.00) | Total=49.00
13. 顾客购买一杯心痛的感觉(LoveFeelings),另加柠檬一份:
点单系统打印出(即小票上要显示的文本):LoveFeelings (49.00) + Lemon (5.0*80%)|Total=53.00
14. 顾客购买一杯心痛的感觉(LoveFeelings),另加所有的调味品各来一份:
点单系统打印出(即小票上要显示的文本):LoveFeelings (49.00) + Honey (4.50*80%)+ Milk(3.50*80%) + Chocolate (7.00*80%) + Mocha (8.0*80%) + Lemon (5.0*80%)| Total=71.40
第五组测试用例(需求变化2):
老板采用了一个员工的建议,研发出一个种新的调味品,叫情人的怀抱(LoversEmbrace)
定价21.00。
调味品(Condiment)价目表*:
序号 |
调味品名称 |
描述 |
价格 |
备注 |
1 |
糖 |
Sugar |
免费 |
|
2 |
牛奶 |
Milk |
3.50 |
|
3 |
蜂蜜 |
Honey |
4.50 |
|
4 |
柠檬 |
Lemon |
5.00 |
|
5 |
巧克力 |
Chocolate |
7.00 |
|
6 |
摩卡 |
Mocha |
8.00 |
|
7 |
情人的怀抱 |
LoversEmbrace |
21.00 |
正常折扣为80%,但如果饮料为 LoveFeelings,则该其折扣为50% |
… |
… |
|
|
|
注:正常情况下调味品LoversEmbrace折扣为80%,但如果顾客点的饮料是LoveFeelings,该调味品可以享受50%的最低折扣!
15. 顾客购买一杯鲜啤(Beer),他想来一份情人的怀抱:
点单系统打印出(即小票上要显示的文本):Beer (18.00)+ LoversEmbrace (21.00*80%)|Total=34.80
16. 顾客购买一杯心痛的感觉(LoveFeelings),他也要了一份情人的怀抱(可享最低折扣):
点单系统打印出(即小票上要显示的文本):LoveFeelings (49.00)+ LoversEmbrace (21.00*50%)|Total=59.50
17. 顾客购买一杯心痛的感觉(LoveFeelings),他要了一份柠檬和一份情人的怀抱:
点单系统打印出(即小票上要显示的文本):LoveFeelings (49.00) + Lemon (5.0*80%) +LoversEmbrace (21.00*50%)| Total=63.50
第六组测试用例(需求变化3):
不久后老板又作了三个经营策略的调整:
1) 老板发现“糖”浪费严重,于是决定“糖”不再免费,而也需要购买,定价1.00/份。
2) 为了灵活,增加收入,决定调味品可以单卖。
3) 每个周五,所有顾客的费用按总价格的90%收取。
18. 顾客购买一杯咖啡(Coffee),另加一份糖:
点单系统打印出(即小票上要显示的文本):Coffee (22.00) + Sugar (1.00)| Total=23.00
19. 顾客购买一份牛奶(Milk):
点单系统打印出(即小票上要显示的文本):Milk (3.50) | Total=3.50
20. 顾客购买了一份柠檬和一份情人的怀抱:
点单系统打印出(即小票上要显示的文本):Lemon (5.0) + LoversEmbrace (21.00*80%)|Total=21.80
21. 今天周五,顾客购买了一杯心痛的感觉(LoveFeelings),他也要了一份柠檬和一份情人的怀抱:
点单系统打印出(即小票上要显示的文本):LoveFeelings (49.00) + Lemon (5.0*80%) +LoversEmbrace (21.00*50%)| Total=63.50*90%=57.15