这里涉及到装饰者与被装饰者。所谓装饰者与被装饰者,就是被装饰者通过装饰者装饰,原有功能得到扩展,而本身代码不会发生变化。
简单的理解就是在原有对象上包装一层附件动作,且保持包装完后的对象与被包装者属于同一个类族,但是额外附加了该包装类所特定的动作。
首先定义一个抽象的类——>Drink,抽象出饮料的价格和名称:
public abstract class Drink {
public String name;
public double price;
public abstract double calcaTotalPrice();
public abstract String getAllName();
public Drink(){
}
public Drink(double price, String name) {
this.name = name;
this.price = price;
}
setter & getter ...
}
接着定义一个被装饰者——>Coffee:
// 被装饰者
public class Coffee extends Drink {
@Override
public double calcaTotalPrice() {
return this.price;
}
public Coffee() {
}
public Coffee(double price, String name) {
super(price, name);
}
public String getAllName() {
return this.getName();
}
}
然后定义一个装饰者——Milk:
public class Milk extends Drink {
private Drink drink;
public Milk() {
}
public Milk(double price, String name, Drink drink) {
super(price, name);
this.drink = drink;
}
@Override
public double calcaTotalPrice() {
return this.price + this.drink.calcaTotalPrice();
}
@Override
public String getAllName() {
return this.getName() + " " + this.drink.getAllName();
}
public Drink getDrink() {
return drink;
}
public void setDrink(Drink drink) {
this.drink = drink;
}
}
一图胜千言,同理,一句代码胜过一通乱**。测试类如下:
public class TestMain {
public static void main(String[] args) {
Coffee coffee = new Coffee(10, "咖啡");
System.err.println(coffee.calcaTotalPrice());
Milk milk = new Milk(5, "香蕉牛奶", coffee);
System.err.println(milk.calcaTotalPrice());
Milk milk1 = new Milk(3, "草莓牛奶", milk);
System.err.println(milk1.calcaTotalPrice());
System.err.println(milk1.getAllName());
}
}
运行结果:
10.0
15.0
18.0
草莓牛奶 香蕉牛奶 咖啡