问题:
咖啡订单项目:
- 咖啡种类/单品咖啡:Espresso(意大利浓咖啡)、ShortBlack、LongBlack(美式咖啡)、Decaf(无因咖啡)
- 调料:Milk、Soy(豆浆)、Chocolate
- 要求在扩展 新的咖啡种类时,具有良好的扩展性、改动方便、维护方便
- 使用OO的来计算不同种类咖啡的 用 费用: 客户可以单点咖啡 ,也可以点咖啡+调料组合(调料可以点多份)。
1.传统方式
由于订单的组合过多,会有很多类,当我们增加一个单品咖啡,或者一个新的调料,类的数量就会倍增,就会出现类爆炸。
2.装饰者模式
装饰者模式可以动态的将新功能附加到对象上。在对象功能扩展方面,它比继承更有弹性,装饰者模式也体现了开闭原则(ocp)。
首先先建立抽象类Drink
public abstract class Drink {
private String des;
private float price = 0.0f;
public String getDes() {
return des;
}
public void setDes(String des) {
this.des = des;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public abstract float cost();
}
再次让Coffee类去继承它(由于咖啡的种类较多,所以将其中共有的属性抽象出来(共有的属性就是都实现Drink类中的抽象方法))
public class Coffee extends Drink{
public float cost() {
System.out.print("一杯" + getDes() + ":" );
return super.getPrice();
}
}
再将各个具体的咖啡类来继承Coffee类
public class Espresso extends Coffee{
public Espresso() {
setDes("意大利浓咖啡");
setPrice(5.5f);
}
}
public class LongBlack extends Coffee{
public LongBlack() {
setDes("美式咖啡");
setPrice(6.0f);
}
}
public class DeCaf extends Coffee{
public DeCaf() {
setDes("无因咖啡");
setPrice(6.5f);
}
}
现在来处理修饰类,注意,这里的cost()方法其实是一个递归方法
public class Decorator extends Drink{
Drink drink;
public Decorator(Drink drink) {
this.drink = drink;
}
@Override
public float cost() {
System.out.print("一杯" + drink.getDes() + ":" + drink.getPrice() + " ,一份" + getDes() + ":" + getPrice() + "共计:" );
return getPrice() + drink.cost();
}
}
#######再将所有的具体修饰类继承Decorator 类
public class Chocolate extends Decorator{
public Chocolate(Drink drink) {
super(drink);
setDes("巧克力");
setPrice(1.5f);
}
}
public class Milk extends Decorator{
public Milk(Drink drink) {
super(drink);
setDes("牛奶");
setPrice(1.0f);
}
}
public class Soy extends Decorator{
public Soy(Drink drink) {
super(drink);
setDes("豆浆");
setPrice(0.5f);
}
}
进行测试:
public class Test {
public static void main(String[] args) {
DeCaf deCaf = new DeCaf();
System.out.println(deCaf.cost());
Milk milk = new Milk(new LongBlack());
System.out.println(milk.cost());
Soy soy = new Soy(new Chocolate(new Espresso()));
System.out.println(soy.cost());
}
}
输出结果
一杯无因咖啡:6.5
一杯美式咖啡:6.0 ,一份牛奶:1.0共计:一杯美式咖啡:7.0
一杯巧克力:1.5 ,一份豆浆:0.5共计:一杯意大利浓咖啡:5.5 ,一份巧克力:1.5共计:一杯意大利浓咖啡:7.5