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

//Drink,饮品抽象类,提取饮品的共同特点public abstract class Drink {private String desr;private float price = 0.0f;public String getDesr() {return desr;}public void setDesr(String desr) {this.desr = desr;}public float getPrice() {return price;}public void setPrice(float price) {this.price = price;}public abstract float cost(); //抽象的计算总价的方法}
//咖啡抽象类,继承饮品类,是饮品的一个分支public abstract class Coffee extends Drink {@Overridepublic float cost() {return super.getPrice();}}//咖啡实现类(具体的咖啡)//黑咖啡public class ShortBlack extends Coffee{public ShortBlack() {setDesr("黑咖啡");setPrice(4.0f);}}//美式咖啡public class American extends Coffee{public American() {setDesr("美式咖啡");setPrice(8.0f);}}
//装饰类,本例中的是调料//注意继承Drink类public abstract class Decorator extends Drink {private Drink drink; //组合一个单品饮料public Decorator(Drink drink) {this.drink = drink;}@Override //重写计算总价的方法,加上调料的价钱public float cost() {return super.getPrice()+drink.cost();}@Override //重写饮品描述的方法public String getDesr() {return super.getDesr()+" "+super.getPrice()+" && "+drink.getDesr();}}//具体调料//巧克力调料public class Chocolate extends Decorator {public Chocolate(Drink drink) {super(drink);setDesr("巧克力");setPrice(1.5f);}}//牛奶调料public class Milk extends Decorator {public Milk(Drink drink) {super(drink);setDesr("牛奶");setPrice(1.0f);}}
//客户类,测试public class Client {public static void main(String[] args) {//Drink drink = new ShortBlack();Drink drink = new American();System.out.print(drink.getDesr());System.out.println(" 总价"+drink.cost());drink = new Milk(drink); //单品美式+牛奶drink = new Chocolate(drink); //单品美式+牛奶+巧克力System.out.print(drink.getDesr());System.out.println(" 总价"+drink.cost());System.out.println(((Decorator)drink).getDrink().getDesr());drink = new Chocolate(drink); ////单品美式+牛奶+巧克力+巧克力System.out.print(drink.getDesr());System.out.println(" 总价"+drink.cost());System.out.println(((Decorator)(((Decorator)drink).getDrink())).getDrink().getPrice());}}

装饰者模式解决星巴克咖啡订单
装饰者模式下的订单:2份巧克力+一份牛奶的LongBlack
说明
- Milk包含了LongBlack
- 一份Chocolate包含了(Milk+LongBlack)
- 一份Chocolate包含了(Chocolate+Milk+LongBlack)
这样不管是什么形式的单品咖啡+调料组合,通过递归方式可以方便的组合和维护
个人总结
此模式适合某对象添加新功能(或者属性)后,顶层都为同一类的对象
