案例说明
现在有几种饮品,都是单品咖啡,顾客可以点单品咖啡也可以点单品咖啡加调料。
首先有一个抽象类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就是上面案例中的调料