从咖啡谈装饰模式

网友投稿 275 2022-11-27

从咖啡谈装饰模式

问题描述

.他们的咖啡有不同的品牌,有latte(拿铁),卡布奇诺(cappuccino)等等当然以后肯定会改变,同时各种咖啡都可以加上milk(牛奶),soy(豆浆),sugar(糖)等配料,当然配料也会改变(一杯咖啡可以加两分牛奶).还有咖啡有大杯小杯.

版本一

一个coffee父类,各种品牌的开发继承之. 语言是苍白的 看代码!

public class Coffee { private String description; //品牌描述 private String size; private int milk; private int sugar; public Coffee(){ //构造函数 description="unknow coffee"; size="small"; } public Coffee(int milk,int sugar,String size,String brand){ this.milk=milk; this.sugar=sugar; this.size=size; description=brand; } public String getDescription(){ return description+" "+size+"杯咖啡 milk:"+milk+"份 sugar:"+sugar+"份"; } public double cost(){ if(size.equals("small")) //小杯大杯分开 return milk*1.1+sugar*1.2; if(size.equals("jourm")) return milk*1.2+sugar*1.4; return 0; }}

然后就是一个拿铁(iatte)继承了coffee 别的品牌都一样的

public class iatte1 extends Coffee{ public double cost(){ return super.cost()+2.5; } public iatte1(int milk,int sugar,String size) { super(milk, sugar, size, "iatte"); }}

再看测试类

import condiment.*;import base.Beverage;import brand.*;public class test { public static void main(String[] args){ Coffee aCoffee=new iatte1(2,3,"small"); System.out.println(aCoffee.getDescription()); System.out.println(aCoffee.cost()); }}

测试结果

iatte  small杯咖啡   milk:2份    sugar:3份

8.3

大家可以看出来 关键的cost()计算和getdescription 都是在父类中完成的.

这样看起来还不错 不过真的不错吗?

几个问题

1:一旦我要更改某一种调料的价格怎么办? 2:我要新增一种调料怎么办? 3:如果有了新的饮料,如茶,问题是茶不会加奶呀 怎么办?

分析这个三个问题

其中1,2违反了开闭原则.第三个的设计也不合适

.

此时我们看看 装饰模式是怎么解决这个问题的.

装饰模式版本

我们建立一个抽象类beverage.

package base;public abstract class Beverage {public String description="unknow coffee";public String size="unknow size";public void setDescription(String description) {this.description = description;}public String getDescription() {return description;} public abstract double cost();}

让所有的咖啡品牌都继承beverage.

package brand;import base.Beverage;public class latte extends Beverage{ public double cost() { if(size.endsWith("jorum")) return 1.5; else if(size.endsWith("small")) return 1.2; return 1.2; } public latte(){ size="jorum"; description="latte jorum coffee"; } public latte(String size2){ size=size2; description="latte "+size+" coffee"; }}

其他品牌类似,不在赘述.

再建立一个所有调料(milk.soy等等)的基类condiment,并让它继承beverage.

package condiment;import base.Beverage;public abstract class condiment extends Beverage { public abstract String getDescription();}

然后所有的配料继承condiment.

package condiment;import base.Beverage;public class sugar extends condiment { Beverage beverage; public sugar(Beverage beverage2){ beverage=beverage2; } public String getDescription() { System.out.print("suga 的形容 \n"); return beverage.getDescription()+" ,sogar"; } public double cost() { return beverage.cost()+2.4; }}

其他配料如milk等似,不在赘述.

uml图如下(取自head first design pattern )

看看测试类.

import condiment.*;import base.Beverage;import brand.*;public class test { public static void main(String[] args){ System.out.println("第一杯"); Beverage aBeverage=new latte(); System.out.println(aBeverage.getDescription()); System.out.println(aBeverage.cost()); System.out.println(); System.out.println("第二杯"); Beverage bBeverage=new cappuccino("small"); bBeverage=new milk(bBeverage); bBeverage=new milk(bBeverage); bBeverage=new sugar(bBeverage); System.out.println(bBeverage.getDescription()); System.out.println(bBeverage.cost()); }}

大家看看,在第二杯的时候,我们给咖啡加糖,加牛奶就new一个牛奶,new一个糖然后加进去很形象不是吗?

测试结果

第一杯

latte jorum coffee

1.5

第二杯

suga 的形容

milk 的形容

milk 的形容

cappuccino small coffee,milk,milk ,sogar

6.1

这里有一个问题,这个小杯的含两份牛奶一份糖的cappuccino的价格到底是怎么算出来的呢?

public double cost() {

return beverage.cost()+2.4;

}

这是糖的cost 。

看咱们的测试代码。Cappuccino最“外边”包的是糖,当我们调用bBeverage.cost()的时候,其实就是用糖的cost。Ok,看上面糖的cost,2.4+beverage.cout()这句代码里的beverage指的是谁呢?

bBeverage=new milk(bBeverage);

bBeverage=new milk(bBeverage);

bBeverage=new sugar(bBeverage);

很显然是牛奶。所以再调用牛奶的cost!继续往上走,所以的问题都解决了。其实我建议朋友们再看这部分的时候最好开启debug模式。亲自一步一步调试一下就解决问题了。

下图来自head first 里面的咖啡例子

whip,mocha都是配料和本例子中的sugar.milk是一回事.darkroast是咖啡的品牌 相当于本例中的卡布奇诺,拿铁.

在javaio中的应用

参考资料

>

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:电力载波芯片ST7538及其应用
下一篇:【搞定Go语言】第3天4:NSQ开源的实时分布式内存消息队列
相关文章

 发表评论

暂时没有评论,来抢沙发吧~