抽象工厂模式下跨工厂调用产品的实现方案问询(披萨配料场景)
这两个问题问得很到位,咱们结合经典的披萨例子一步步拆解清楚:
在抽象工厂模式里,每个工厂的职责是产出一套内聚的产品族(比如全套纽约风格披萨配料,或是全套芝加哥风格配料)。默认情况下,单个工厂不会直接“调用”其他工厂——这会破坏模式对产品族的封装性。
实际上,整合不同工厂产品的职责落在客户端代码(或是使用工厂的高层模块)上,具体做法通常是这样的:
- 为不同的产品族定义独立的抽象工厂(比如单独的
面团工厂、芝士工厂,不过披萨例子里我们一般用一个披萨配料工厂涵盖所有配料)。 - 客户端(比如
披萨店或披萨类)持有多个抽象工厂的实例。 - 创建产品(比如披萨)时,客户端分别调用各个工厂的对应方法来获取所需组件。
举个例子:如果你想做一款“纽约酱+芝加哥厚底”的披萨,你的披萨类可以在构造方法中同时接收纽约配料工厂和芝加哥配料工厂实例,然后调用芝加哥工厂.createDough()获取厚底,调用纽约工厂.createSauce()获取纽约酱,再组装成披萨。
如果需要更结构化的跨工厂使用方式,你也可以创建一个外观工厂,它包装多个底层工厂并对外提供组合后的产品创建方法——但这依然是客户端侧的逻辑,而非工厂之间直接交互。
先梳理下现有基础结构:
PizzaIngredientFactory是抽象工厂,定义了createDough()等配料创建方法。NYPizzaIngredientFactory实现该接口,返回ThinCrustDough;ChicagoPizzaIngredientFactory返回ThickCrustDough。PizzaStore是抽象工厂方法类,通过createPizza()方法使用配料工厂制作披萨。
以下是不使用Builder的解决方案:
步骤1:创建混合配料工厂(扩展抽象工厂)
我们定义一个新的具体工厂,继承自PizzaIngredientFactory,只重写createDough()方法来返回芝加哥风格的厚底,其他配料方法则保留纽约工厂的逻辑:
public class NYWithChicagoDoughIngredientFactory implements PizzaIngredientFactory { @Override public Dough createDough() { // 复用芝加哥工厂的厚底实现 return new ThickCrustDough(); } @Override public Sauce createSauce() { // 保留纽约的 marinara 酱 return new MarinaraSauce(); } @Override public Cheese createCheese() { // 保留纽约的马苏里拉芝士 return new ReggianoCheese(); } // 根据需要重写其他配料方法,保持与纽约工厂一致 }
这个工厂完全符合抽象工厂的契约——它能产出一套合法的披萨配料,只是把面团替换成了芝加哥风格的版本。
步骤2:用工厂方法创建披萨
接下来,创建一个新的PizzaStore子类,在它的createPizza()方法中使用这个混合工厂:
public class NYWithChicagoDoughPizzaStore extends PizzaStore { @Override protected Pizza createPizza(String type) { Pizza pizza = null; PizzaIngredientFactory ingredientFactory = new NYWithChicagoDoughIngredientFactory(); if (type.equals("cheese")) { pizza = new CheesePizza(ingredientFactory); pizza.setName("纽约风格芝士披萨(配芝加哥厚底)"); } // 按需添加其他披萨类型的创建逻辑 return pizza; } }
步骤3:组装并使用披萨
当你实例化这个披萨店并下单时,它就会用混合工厂获取ThickCrustDough,同时保留其他纽约风格配料——全程不需要用到Builder模式。
核心思路是:我们利用抽象工厂的契约创建了自定义的产品族,再通过工厂方法模式封装披萨的创建逻辑,完全贴合两种模式的设计,没有引入额外的Builder。
内容的提问来源于stack exchange,提问作者crashovski

