// 饮料的基类
//(抽象组件)
public abstract class Beverage {
String description = "Unknown Beverage";
public String getDescription() {
return description;
}
public abstract double cost();
}
/**
* 调料抽象类,也就是装饰者
* (抽象装饰者)
* @author Kevintan
*
*/
public abstract class CondimentDecorator extends Beverage {
/**
* 首先必须让CondimentDecorator 能够取代Beverage
* 所以必须让CondimentDecorator扩展自Beverage类
*
* 第二,所有的调料装饰者都必须重新实现getDescription()方法
* 为什么?
* 因为为了能够把调料和饮料的描述组合起来
*
*/
public abstract String getDescription();
@Override
public double cost() {
// TODO Auto-generated method stub
return 0;
}
}
/**
* 这种另外一种饮料,做法跟Espresso一样
* (具体组件)
* @author kevintan
* 当然你也可以自行建立另外的饮料类: DarkRoast 和 Decaf 做法一样
*/
public class HouseBlend extends Beverage {
public HouseBlend() {
description = "House Blend Coffee";
}
@Override
public double cost() {
return .89;
}
}
**
* 这种另外一种饮料,做法跟Espresso一样
* (具体组件)
* @author kevintan
* 当然你也可以自行建立另外的饮料类: DarkRoast 和 Decaf 做法一样
*/
public class HouseBlend extends Beverage {
public HouseBlend() {
description = "House Blend Coffee";
}
@Override
public double cost() {
return .89;
}
}
/**
* 摩卡是一个装饰者
* (具体的装饰者)
* 所以让它扩展自CondimentDecorator
* @author Kevintan
*
*/
public class Mocha extends CondimentDecorator {
/*
* 要让Mocha能够引用Beverage,做法如下
* 1.用一个实例变量记录饮料,也就就是被装饰者
* 2.想办法让被装饰者(饮料),被记录到实例变量中 (这里是构造器)
*/
Beverage beverage;
public Mocha(Beverage beverage) {
this.beverage = beverage;
}
@Override
public String getDescription() {
//我们希望叙述不只是饮料,而是完整的连调料都描述出来
return beverage.getDescription() + ", Mocha";
}
// 要计算Mocha饮料的价钱,首先把调用委托给装饰者对象,以计算价钱,
//然后再加上Mocha的价钱,得到最后结果
public double cost() {
return 0.20 + beverage.cost();
}
}
**
* 跟Mocha一样,是一个装饰者
* @author Kevintan
*
*/
public class Soy extends CondimentDecorator {
Beverage beverage;
public Soy(Beverage beverage) {
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription() + ", Soy";
}
public double cost() {
return .21 + beverage.cost();
}
}
/**
* 跟Mocha一样,是一个装饰者
* @author Kevintan
*
*/
public class Whip extends CondimentDecorator {
Beverage beverage;
public Whip(Beverage beverage) {
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription() + ", Whip";
}
public double cost() {
return .11 + beverage.cost();
}
}
/**
* 是时候舒服地坐下来,点一些咖啡
* 看看利用装饰者模式设计出的灵活的系统是多么神奇了
* @author Kevintan
*
*/
public class StarbuzzCoffee {
public static void main(String[] args) {
//订一杯Espresso,不需要调料,打印出它的描述和价格
Beverage beverage = new Espresso();
System.out.println(beverage.getDescription() + " $" + beverage.cost());
//订一杯调料为豆浆,摩卡,奶泡的HouseBlend咖啡
Beverage beverage2 = new HouseBlend();
beverage2 = new Soy(beverage2);
beverage2 = new Mocha(beverage2);
beverage2 = new Whip(beverage2);
System.out.println(beverage2.getDescription() + " $" + beverage2.cost());
}
}
总结:
设计原则:(开放-关闭原则)类应该对扩展开放,对修改关闭。
装饰者模式:动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。