Java披萨装饰器模式实现问题:配料未加入TopingDecorator集合
装饰器模式实现披萨配料系统的正确方案
嘿,我来帮你搞定这个装饰器模式的披萨程序问题!看起来你之前尝试用ArrayList来存储配料的思路走偏了——装饰器模式的核心是层层包装对象,而不是在基础披萨里维护一个配料列表。我给你整理了完整的正确实现,包括你需要的两种披萨和四种配料,还有添加三种配料的示例。
核心结构说明
装饰器模式的关键是:
- 抽象的
Pizza类定义所有披萨(包括基础披萨和带配料的披萨)的通用行为 ToppingDecorator作为抽象装饰器,持有一个Pizza对象的引用,用来包装底层披萨- 具体配料类继承
ToppingDecorator,重写方法来添加自己的描述和成本
1. 抽象披萨类
首先定义所有披萨的基础接口:
public abstract class Pizza { protected String description = "Unknown Pizza"; public String getDescription() { return description; } public abstract double getCost(); }
2. 具体基础披萨类
实现你需要的美式和那不勒斯披萨:
// 美式披萨 public class American extends Pizza { public American() { description = "American Pizza"; } @Override public double getCost() { return 8.99; // 基础价格 } } // 那不勒斯披萨 public class Neapolitan extends Pizza { public Neapolitan() { description = "Neapolitan Pizza"; } @Override public double getCost() { return 9.99; // 基础价格 } }
3. 抽象配料装饰器
这个类是装饰器模式的核心,它继承自Pizza,同时持有一个Pizza对象的引用,用来包装底层的披萨(可以是基础披萨,也可以是已经加过配料的披萨):
public abstract class ToppingDecorator extends Pizza { protected Pizza pizza; public ToppingDecorator(Pizza pizza) { this.pizza = pizza; } // 默认转发底层披萨的描述和成本,具体配料类会重写这些方法 @Override public String getDescription() { return pizza.getDescription(); } @Override public double getCost() { return pizza.getCost(); } }
4. 具体配料类
实现你需要的四种配料,每个都继承ToppingDecorator,并添加自己的信息:
// 萨拉米配料 public class Salami extends ToppingDecorator { public Salami(Pizza pizza) { super(pizza); } @Override public String getDescription() { return pizza.getDescription() + ", Salami"; } @Override public double getCost() { return pizza.getCost() + 1.50; // 配料价格 } } // 苏杜克香肠配料 public class Soudjouk extends ToppingDecorator { public Soudjouk(Pizza pizza) { super(pizza); } @Override public String getDescription() { return pizza.getDescription() + ", Soudjouk"; } @Override public double getCost() { return pizza.getCost() + 1.75; } } // 洋葱配料 public class Onion extends ToppingDecorator { public Onion(Pizza pizza) { super(pizza); } @Override public String getDescription() { return pizza.getDescription() + ", Onion"; } @Override public double getCost() { return pizza.getCost() + 0.75; } } // 辣椒配料 public class Pepper extends ToppingDecorator { public Pepper(Pizza pizza) { super(pizza); } @Override public String getDescription() { return pizza.getDescription() + ", Pepper"; } @Override public double getCost() { return pizza.getCost() + 0.50; } }
添加配料的正确方式
按照你说的“Add Pizza”指令,我们可以像这样给披萨添加三种配料(比如给美式披萨加萨拉米、苏杜克香肠和洋葱):
public class PizzaOrderDemo { public static void main(String[] args) { // 1. 创建基础美式披萨 Pizza myPizza = new American(); // 2. 添加第一种配料:萨拉米 myPizza = new Salami(myPizza); // 3. 添加第二种配料:苏杜克香肠 myPizza = new Soudjouk(myPizza); // 4. 添加第三种配料:洋葱 myPizza = new Onion(myPizza); // 输出订单信息 System.out.println("Your Pizza: " + myPizza.getDescription()); System.out.println("Total Cost: $" + String.format("%.2f", myPizza.getCost())); } }
运行这段代码,你会得到这样的输出:
Your Pizza: American Pizza, Salami, Soudjouk, Onion Total Cost: $13.09
为什么之前的ArrayList方式不对?
装饰器模式的设计初衷是动态地给对象添加额外职责,通过层层包装的方式,而不是在基础披萨里维护一个配料列表:
- 如果用ArrayList存储配料,会把披萨和配料的逻辑耦合在一起,违反了开闭原则(添加新配料时需要修改Pizza类)
- 装饰器模式让每个配料都是独立的类,符合单一职责原则,修改某个配料的价格或描述不会影响其他部分
- 你可以灵活组合任意多种配料,甚至调整添加顺序,完全不需要修改现有代码
内容的提问来源于stack exchange,提问作者Habil Ganbarli
相关产品推荐
相关产品推荐

