案例说明
现在有几种饮品,都是单品咖啡,顾客可以点单品咖啡也可以点单品咖啡加调料。
首先有一个抽象类Drink
@Data
public abstract class Drink {
//描述
private String desc;
//价格
private float price = 0.0f;
//计算价格的方法
public abstract float cost();
}
然后有一个咖啡类继承Drink
public class Coffee extends Drink{
@Override
public float cost() {
//不加调料的单品咖啡就是他的原价
return getPrice();
}
}
一种意大利咖啡继承咖啡类
public class Expresso extends Coffee{
public Expresso(){
setDesc("意大利咖啡");
setPrice(6f);
}
}
一种美式咖啡继承咖啡类
public class LongBlack extends Coffee {
public LongBlack(){
setDesc("美式咖啡");
setPrice(10f);
}
}
然后有一个装饰者类继承Drink,其中聚合了一个被装饰者对象
public 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 getDesc() {
return super.getDesc() + super.getPrice() + drink.getDesc();
}
}
有一个巧克力类继承装饰者类
public class Chocolate extends Decorator {
public Chocolate(Drink drink) {
super(drink);
setDesc("巧克力");
setPrice(2f);
}
}
有一个牛奶类继承装饰者类
public class Milk extends Decorator {
public Milk(Drink drink) {
super(drink);
setDesc("牛奶");
setPrice(1f);
}
}
这时可以创建一个咖啡厅类来点咖啡了
public class CoffeeBar {
public static void main(String[] args) {
//1 点一份单品美式咖啡
Drink order = new LongBlack();
System.out.println("费用:"+order.cost());
//2 加入一份牛奶
order = new Milk(order);
System.out.println("费用:"+order.cost());
//3 加入一份巧克力
order = new Chocolate(order);
System.out.println("费用:"+order.cost());
}
}
输出结果
如果再添加一种新的咖啡或者一种新的调料,只需要去继承咖啡类或者装饰者类即可
装饰者模式在jdk中io流中有使用到
java的io结构中有一个InputStream类,这个类就好比上面案例中的Drink类
他的子类中有FileInputStream、StringBufferInputStream、ByteArrayInputStream,这几个就相当于上面案例中的单品咖啡,也就是被装饰者。
InputStream的子类还有一个FilterInputStream就是装饰者,FilterInputStream下面有几个子类,
BufferInputStream、DataInputStream、LineNumberInputStream就是上面案例中的调料