笔记来源:尚硅谷
一、需求
星巴克咖啡订单项目(咖啡馆) :
- 咖啡种类/单品咖啡: Espresso(意大利浓咖啡)、 ShortBlack、 LongBlack(美式
咖啡)、Decaf(无因咖啡)- 调料: Milk、 Soy(豆浆)、 Chocolate
- 要求在扩展新的咖啡种类时,具有良好的扩展性、改动方便、维护方便
- 使用面向对象的方法来计算不同种类咖啡的费用:客户可以点单品咖啡,也可以单品咖
啡+调料组合。
二、装饰者方法
说明
- Drink类就是抽象类
- LongBlack是单品咖啡
- Decorator是一一个装饰类,含有一个被装饰的对象(Drink obj)
- Decorator的cost方法进行一个费用的叠加计算,递归的计算价格
Drink类:
public abstract class Drink {
private String des;//描述
private float price = 0.0f;
//计算费用的抽象方法
//子类实现
public abstract float cost();
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public String getDes() {
return des;
}
public void setDes(String des) {
this.des = des;
}
}
创建LongBlack(美式咖啡)类来继承Drink:
public class LongBlack extends Drink{
public LongBlack() {
setDes("LongBlack");
this.setPrice(10.0f);
}
@Override
public float cost() {
return getPrice();
}
}
创建装饰者:
public class Decorator extends Drink {
private Drink obj;
//组合Drink
public Decorator(Drink obj) {
this.obj = obj;
}
@Override
public float cost() {
//getPrice()自己的价格
//递归计算cost
return super.getPrice() + obj.cost();
}
@Override
public String getDes() {
return des + " " + super.getPrice() + " " + obj.getDes();
}
}
创建装饰者特例Milk:
public class Milk extends Decorator {
public Milk(Drink obj) {
super(obj);
setDes("牛奶");
setPrice(3.0f);
}
}
Client调用示例如下:
public class Client {
public static void main(String[] args) {
//点一杯美式咖啡
Drink drink = new LongBlack();
//点牛奶调料
drink = new Milk(drink);
//点牛奶调料
drink = new Milk(drink);
//计算价格
System.out.println(drink.cost());
}
}
输出如下:
三、装饰者模式的JDK应用
在 JDK 的 I/O中,我们列举出部分关系(FilterInpuStream相当于Decorator):
// FilterInpuStream相当于Decorator,充当了装饰者
// (version 1.8 : 52.0, super bit)
public class java.io.FilterInputStream extends java.io.InputStream {
// Field descriptor #25 Ljava/io/InputStream;
protected volatile java.io.InputStream in; //--组合了InputStream
// Method descriptor #26 (Ljava/io/InputStream;)V
// Stack: 2, Locals: 2
protected FilterInputStream(java.io.InputStream arg0);
/*省略*/
}