装饰者模式定义:
装饰者模式:动态的将新功能附加到对象上,在对象功能扩展方面,它比继承更有弹性,装饰者模式也体现了开闭原则
案例:咖啡订单
1.咖啡种类:Espresso(意大利浓咖啡)、ShortBlack、LongBlack(美式咖啡)、Decaf(无因咖啡)
2.调料:Milk、Soy(豆浆)、Chocolate
3.要求在扩展新的咖啡种类时,具有良好的扩展性、改动方便、维护方便
4.使用OO的来计算不同种类咖啡的费用:客户可以点单品咖啡、也可以单品咖啡+调料组合
方案1:

Drink是一个抽象类 表示饮料
description就是对咖啡的描述,比如咖啡的名字
cost()是计算费用,Drink中做成一个抽象方法
Decaf就是单品咖啡,继承Drink,并实现cost
Espress&&Milk就是单品咖啡+饮料,这个组合很多
问题:这样设计,会有很多类,当我们增加一个单品咖啡,或者一个新的调料,类的数量就会倍增,就会出现类爆炸
采用装饰者模式:

Drink:
public abstract class Drink {
public 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();
}
Decorator及其子类
public class Decorator extends Drink {
private Drink obj;
public Decorator(Drink obj){
this.obj=obj;
}
@Override
public float cost() {
return super.getPrice()+obj.cost();
}
public String getDes(){
return super.des+" "+super.getPrice()+"&&"+obj.getDes();
}
}
//调味品
public class Chocolate extends Decorator {
public Chocolate(Drink obj) {
super(obj);
setDes("chocolate");
setPrice(3.0f); //调味品价格
}
}
public class Milk extends Decorator {
public Milk(Drink obj) {
super(obj);
setDes("牛奶");
setPrice(2.0f);
}
}
public class Soy extends Decorator {
public Soy(Drink obj) {
super(obj);
setDes("都将");
setPrice(1.5f);
}
}
Coffee及其子类:
public class Coffee extends Drink{
@Override
public float cost() {
return super.getPrice();
}
}
public class Espresso extends Coffee{
public Espresso(){
setDes("意大利咖啡");
setPrice(6.0f);
}
}
public class LongBlack extends Coffee{
public LongBlack(){
setDes("longblack");
setPrice(5.0f);
}
}
public class ShortBlack extends Coffee {
public ShortBlack(){
setDes("shortblack");
setPrice(4.0f);
}
}
点单:
public class CoffeeBar {
public static void main(String[] args) {
//点一份LonBlack
Drink longBlack = new LongBlack();
System.out.println(longBlack.cost());
System.out.println(longBlack.getDes());
//2 加入牛奶
Milk milk = new Milk(longBlack);
System.out.println(milk.cost());
System.out.println(milk.getDes());
}
}