t对象的价格加上当前装饰者的价格
@Override
public double cost() {
return food.cost() + 2D;
}
@Override
public String getDesc() {
return food.getDesc()+" + "+this.desc;
}
}
public class Mushroom extends FoodDecorator {
String desc = "香菇";
Food food;
public Mushroom(Food food){
this.food = food;
}
// 计算总价
@Override
public double cost() {
return food.cost() + 2D;
}
@Override
public String getDesc() {
return food.getDesc()+" + "+this.desc;
}
}
public class Potato extends FoodDecorator {
String desc = "土豆";
Food food;
public Potato(Food food){
this.food = food;
}
// 计算总价
@Override
public double cost() {
return food.cost() + 2D;
}
@Override
public String getDesc() {
return food.getDesc()+" + "+this.desc;
}
}
public class Veg extends FoodDecorator {
String desc = "蔬菜";
Food food;
public Veg(Food food){
this.food = food;
}
// 计算总价
@Override
public double cost() {
return food.cost() + 1.5D;
}
@Override
public String getDesc() {
return food.getDesc()+" + "+this.desc;
}
}
装饰者的所有角色都实现完了,我们来测试一下使用装饰者模式之后的黄焖鸡结账系统,编写一个App
测试类。
public class App {
public static void main(String[] args) {
// 点一份米饭
Rice rice = new Rice();
// 加个鸡蛋
Egg egg = new Egg(rice);
// 在加土豆
Potato potato = new Potato(egg);
// 再加一份白菜
Veg veg = new Veg(potato);
System.out.println(veg.getDesc());
System.out.println(veg.cost());
}
}
测试结果
我们的描述和金额都是正确的,可能你还是没怎么明白装饰者模式,一起来看看我们的黄焖鸡米饭被装饰后的示意图:
我们的黄焖鸡米饭共有三层装饰,第一层是鸡蛋,第二层是土豆,第三层是蔬菜。我们在最后调用价格计算和商品描述都是调用了最外层的装饰者的方法,有点像递归一样,每一层的装饰者都有被前一个装饰者装饰后的黄焖鸡米饭对象。里面会产生想递归一样的调用。希望看完这张图之后,对你理解装饰者模式有帮助。
使用装饰者模式之后的黄焖鸡米饭结账系统,在新增配菜或者产品时,我们不需要修改原先的功能,只需要对类进行扩展就好了,这完全遵循了开放-关闭原则
。
装饰者模式的优点
- 装饰类和被装饰类可以独立发展,而不会互相耦合,换句话说,就是
Component
类无须知道Decorator
类,Decorator
类也不用知道具体的被装饰者。
- 装饰者模式是继承关系的一个替代方案,从上面的黄焖鸡米饭的案例中,我们可以看出,不管装饰多少层,返回的对象还是
Component
- 装饰者模式可以动态的扩展一个实现类的功能
装饰者模式的优点
- 多层装饰模式比较复杂,你可以想象一下剥洋葱,如果最里面的装饰出了问题,你的工作量会有多大?
最后多说一句,JDK 中的 java.io
就是用装饰者模式实现的,有兴趣的可以去深入了解一下。
源代码
文章不足之处,望大家多多指点,共同学习,共同进步
最后
打个小广告,欢迎扫码关注微信公众号:「平头哥的技术博文」,一起进步吧。