1、需求
制作咖啡
1、咖啡的单品种类:Espresso(意大利浓咖啡)、 ShortBlack、 LongBlack(美式
咖啡)、Decaf(无因咖啡)
2、可加的调料:Milk、 Soy(豆浆)、 Chocolate
2、方案一
枚举所有的咖啡方案,把所有的单品种类咖啡和加各种调料的可能的类都实现一遍。
public abstract class coffee {
int price;
public int cost() {
return this.price;
}
}
public class coffee_Espresso extends coffee {
}
public class coffee_ShortBlack extends coffee {
}
public class coffee_LongBlack extends coffee {
}
public class coffee_Decaf extends coffee {
}
public class coffee_Decaf_Milk extends coffee {
}
public class coffee_Decaf_Soy extends coffee {
}
public class coffee_Decaf_Chocolate extends coffee {
}
public class coffee_Decaf_Milk_Soy extends coffee {
}
...
3、方案二
上一个方案的复杂点在于如果有很多种调料,就需要把这些调料的所有排列组合都枚举一遍。所以直接在抽象类中设置相应的属性,判断有没有添加这些调料。这时,需要的类就减少到4种。
public abstract class coffee {
int basicPrice;
int milkPrice;
int soyPrice;
int chocolatePrice;
int hasMilkSize;
int hasSoySize;
int hasChocolateSize;
public int cost() {
int totalPrice = this.basicPrice;
totalPrice += hasMilk * milkPrice;
totalPrice += hasSoy * soyPrice;
totalPrice += hasChocolate * chocolatePrice;
return totalPrice;
}
}
public class coffee_Espresso extends coffee {
}
public class coffee_ShortBlack extends coffee {
}
public class coffee_LongBlack extends coffee {
}
public class coffee_Decaf extends coffee {
}
3、方案三
上一个方案尽管控制了类的数量,但是如果改变调料种类,还需要重新修改相关代码。所以,使用装饰器模式解决这一问题。
装饰器模式举例:送礼物
- 主体:礼物本身,比如玩具、衣服、瓷器等
- 包装:比如包装盒、彩带、贴纸等
将上述示例进一步抽象:
- Component:主体
- ConcreteComponent:具体的主体
- Decorator:装饰(注意这里还包含组合关系)
- ConcreteDecorator:具体的装饰
制作咖啡思路:咖啡和调料都算饮料,主体是饮料。饮料到单品咖啡之间增加过渡层咖啡。
需求:ShortBlack咖啡 + 牛奶 * 2 + 巧克力 * 1,花多少钱?此时只需要递归计算花多少钱。
代码实现
@Data
public abstract class Drink {
private String des;//描述
private float price = 0.0f;
//计算费用的抽象方法
//子类实现
public abstract float cost();
}
咖啡
@Data
public class Coffee extends Drink {
@Override
public float cost() {
return super.getPrice();
}
}
4种单品咖啡
public class Espresso extends Drink{
public Espresso() {
setDes("Espresso");
this.setPrice(8.0f);
}
@Override
public float cost() {
return getPrice();
}
}
public class ShortBlack extends Drink{
public ShortBlack() {
setDes("ShortBlack");
this.setPrice(10.0f);
}
@Override
public float cost() {
return getPrice();
}
}
public class LongBlack extends Drink{}
public class Decaf extends Drink{}
调料
public class Decorator extends Drink {
private Drink obj;
//组合Drink
public Decorator(Drink obj) {
this.obj = obj;
}
@Override
public float cost() {
//getPrice()自己的价格
//递归计算cost
return super.getPrice() + obj.cost();
}
@Override
public String getDes() {
//输出被装饰者的信息
return super.des + " " + super.getPrice() + " && " + obj.getDes();
}
}
3种具体调料
public class Milk extends Decorator {
public Milk() {
super(obj);
setDes("Milk");
this.setPrice(3.0f);
}
@Override
public float cost() {
return getPrice();
}
}
public class Soy extends Decorator {}
public class Chocolate extends Decorator {}
如何使用呢?
public class CoffeeBar {
public static void main(String[] args) {
//点一杯美式咖啡
Drink order = new LongBlack();
//点牛奶调料
order = new Milk(order);
//点牛奶调料
order = new Milk(order);
//计算价格
System.out.println(order.cost());
}
}