有趣。我建议对图表进行一些更改,使其符合 GoF 定义的经典 Builder 模式。
最大的区别在于,在构建器模式中,“主管”不知道构建器的细节。因此,与其拥有一个名为NyPizzaStore 的类和一个名为createPizza() 的方法(显然)非常适合创建纽约风格的比萨饼,不如你可能有一个类调用PizzaChef,它接收一个类的实例:定制如何制作比萨的细节。 (对于这个例子/类比,让我们将 renamePizzaIngerdientFactory 重命名为 Recipe 以便我们可以稍微不同地对待它)。这给了你PizzaChef.createPizza(Recipe r)。 PizzaChef 类不需要担心蛤蜊是新鲜的还是冷冻的,他只需依次调用每个构建器并创建所需的披萨。这是差异的关键……只有一个 PizzaChef,他不知道食谱的细节(子类)。
这样做的一个很好的副作用是,您可以轻松混合和匹配构成 Recipe 类的构建器,这样您就可以使用与 NYStyle 相同的所有成分构建器来创建 NewHavenStyle 披萨,但换成BrickFiredThinCrust 代替。更可定制。 Recipe 成为构建器实例的持有者。
当然,现在我饿了:)
请注意不要混淆模式的名称(这是一种几乎总是涉及多个对象/参与者/角色的可重用技术)和模式中特定角色的名称。此外,模式通常建立在彼此之上并且有很多重叠。
在 Builder pattern 中,有一个 Director 对象,它有一个 createSomething() 方法(不调用它)。该方法将以一种非常公式化的方式调用一个或多个部分构建器。客户端引用了Director,并传入了构建器。客户直接或间接地影响构建的内容。 Director 不需要是任何东西的子类,它可以是一个简单的、密封的类。 PizzaChef 不是客户而是导演。它不会从任何东西继承,也不会被继承。在这种情况下,客户端可能类似于 Customer 类。
现在,正如 Abstract Factory 模式是基于一组 Factory Methods (来自该名称的模式),您可以让 Builder 模式使用 Abstract Factory 。您可以将构建器作为 AbstractFactory 传递给 Director。在这种情况下,Recipe 将是您的 AbstractFactory,NyStyleRecipe 将继承 Recipe 并提供 PizzaChef 类将用于创建比萨饼的构建器方法。在这个特定的实现中,Builder 模式的Directpr 确实是您原始图表中描述的客户端。
但正如我之前试图暗示的那样,这并不是实现Builder 模式的唯一必要条件,我认为它增加了 Builder 旨在克服的限制。我会改用可组合的Recipe 类,因为这样您就可以更轻松地混合搭配成分。 真的薄皮和纽约风格的披萨之间没有联系。纽黑文风格也使用细风格。
Recipe newyorkStyle = new Recipe(
new ThinCrustBuilder(),
new RedSauceBuilder(),
new FreshClamsBuilder(),
new ElectricOvenBuilder());
Recipe newhavenStyle = new Recipe(
new ThinCrustBuilder(),
new WhiteSauceBuilder(),
new FreshClamsBuilder(),
new BrickOvenBuilder());
PizzaChef chef = new PizzaChef ();
nyPizza = checf.createPizza(newyorkStyle);
nhPizza = checf.createPizza(newhavenStyle);
请注意,我使用可组合构建器来重复使用薄壳和新鲜蛤蜊。使用Abstract Factory 就不会那么容易了
我希望能进一步澄清差异!