写在前面的话:
该模式动态的将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。装饰者可以在被装饰者的行为前面与/或后面加上自己的行为,甚至将被装饰者的行为整个取代掉,而达到特定的目的。
该模式的实现意味着一群装饰者类,这些类反映出被装饰的组件类型,用来包装具体组件。
缺点在于,可以用无数个装饰者包装一个组件,但会导致设计中出现许多小对象,如果过度引用,会让程序变得很复杂。
案例分析:
需求:模拟 StarbuzzCoffee 的订单系统,咖啡原种类为Espresso,HouseBlend,添加调料种类分别为Soy,Mocha,Whip,对应不同的收费,杯子分为大中小三种,分别对应不同的收费
代码实现:
1)咖啡部分:
public abstract class Beverage { String description = "Unknown Beverage"; public String getDescription(){ return description; } public abstract double cost(); } public class Espresso extends Beverage { public Espresso() { description = "Espresso"; } @Override public double cost() { return 1.99; } } public class HouseBlend extends Beverage { public HouseBlend() { description = "HouseBlend"; } @Override public double cost() { return 0.89; } }
2)调料部分:
public abstract class CondimentBeverage extends Beverage { public abstract String getDescription(); } public class Soy extends CondimentBeverage { Beverage beverage; public Soy(Beverage beverage) { this.beverage = beverage; } @Override public String getDescription() { return beverage.getDescription(); } @Override public double cost() { return 0.30+beverage.cost(); } } public class Mocha extends CondimentBeverage { Beverage beverage; public Mocha(Beverage beverage) { this.beverage = beverage; } @Override public String getDescription() { return beverage.getDescription(); } @Override public double cost() { return 0.20+beverage.cost(); } } public class Whip extends CondimentBeverage { Beverage beverage; public Whip(Beverage beverage) { this.beverage = beverage; } @Override public String getDescription() { return beverage.getDescription(); } @Override public double cost() { return 0.40+beverage.cost(); } }
3) 杯子选择:
public abstract class Size extends Beverage { public abstract String getDescription(); } public class BigSize extends Size { Beverage beverage; public BigSize(Beverage beverage) { this.beverage = beverage; } @Override public String getDescription() { return beverage.getDescription(); } @Override public double cost() { return 0.30+beverage.cost(); } } public class MiddleSize extends Size { Beverage beverage; public MiddleSize(Beverage beverage) { this.beverage = beverage; } @Override public String getDescription() { return beverage.getDescription(); } @Override public double cost() { return 0.20+beverage.cost(); } } public class SmalleSize extends Size { Beverage beverage; public SmalleSize(Beverage beverage) { this.beverage = beverage; } @Override public String getDescription() { return beverage.getDescription(); } @Override public double cost() { return 0.10+beverage.cost(); } }
4)测试代码---生产订单:
public class StarbuzzCoffee { public static void main(String[] args) { Beverage beverage1 = new Espresso(); //订一杯Espresso,不添加任何调料 System.out.println(beverage1.getDescription()+":$"+beverage1.cost()); Beverage beverage2 = new HouseBlend(); //订一杯HouseBlend,不添加任何调料 beverage2 = new Mocha(beverage2); beverage2 = new Mocha(beverage2); //两份摩卡 System.out.println(beverage2.getDescription()+"(double Mocha):$"+beverage2.cost()); beverage2 = new Soy(beverage2); //再加一份soy System.out.println(beverage2.getDescription()+"(additional Soy):$"+beverage2.cost()); beverage2 = new Whip(beverage2); //再加一份whip System.out.println(beverage2.getDescription()+"(additional Whip):$"+beverage2.cost()); beverage2 = new MiddleSize(beverage2); //选择中杯 System.out.println(beverage2.getDescription()+"(choose middleSize):$"+beverage2.cost()); } }
测试结果:
Espresso:$1.99
HouseBlend(double Mocha):$1.29
HouseBlend(additional Soy):$1.59
HouseBlend(additional Whip):$1.99
HouseBlend(choose middleSize):$2.19