设计模式——装饰者模式
装饰者模式
用于多个类可以相互组合,甚至多数量,多类品组合,而组合完,我们还要访问它们的某个都拥有的属性;这种多变的场景就非常适合装饰者模式
比如以下例子:
咖啡馆:
咖啡品类:无因咖啡、黑咖啡、意大利咖啡等
调料品类: 牛奶、豆浆、巧克力等
客户可以点一杯咖啡 + 若干牛奶、豆浆、咖啡的,搅拌在一起的咖啡,但并不是一次要的,如果一开始就是确定的就没这么绕了,比如一次要一个牛奶,然后觉得不好,再加其他的之类的。
先定义一个所有类的父类Drink
public abstract class Drink {
public String des;//描述
private float price = 0.0f;
public String getDes() {
return des;
}
public void setDes(String des) {
this.des = des;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
//计算费用的抽象方法,子类实现
public abstract float cost();
}
再定义一个装饰者类,用于作为调料的父类
public abstract 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 getDes() {
//drink.getDes() 输出被封装者的信息
return des+" " + getPrice() + " &&" + drink.getDes();
}
}
定义一个咖啡类,作为所以咖啡的父类
public abstract class Coffee extends Drink {
@Override
public float cost() {
return super.getPrice();
}
}
定义黑咖啡类
public class LongBlack extends Drink {
public LongBlack() {
setDes("longblack");
setPrice(5.0f);
}
}
定义调料牛奶
public class Milk extends Decorator {
public Milk(Drink drink) {
super(drink);
setDes("牛奶");
setPrice(2.0f);
}
}
定义调料巧克力
public class Chocolate extends Decorator {
public Chocolate(Drink drink) {
super(drink);
setDes("巧克力");
setPrice(3.0f);//调味品的价格
}
}
用法:
public class CoffeeBar {
public static void main(String[] args){
//1.点一份LongBlack
Drink drink = new LongBlack();
System.out.println("费用=" + drink.cost());
System.out.println("描述="+ drink.getDes());
//2.加一份牛奶
drink = new Milk(drink);
System.out.println("加入一份牛奶 费用= " + drink.cost());
System.out.println(" 加入一份牛奶 描述= "+ drink.getDes());
//3.加一份巧克力
drink = new Chocolate(drink);
System.out.println("加入一份巧克力 费用= " + drink.cost());
System.out.println(" 加入一份巧克力 描述= "+ drink.getDes());
// 4. 再加入一份巧克力
drink = new Chocolate(drink);
System.out.println("order 加入一份牛奶 加入 2 份巧克力 费用 =" + drink.cost());
System.out.println("order 加入一份牛奶 加入 2 份巧克力 描述 = " + drink.getDes());
}
}