How to choose between Factory method pattern and Abstract factory pattern
我知道以前也问过类似的问题。在过去的几天里,我读了很多关于这个的文章,我想我现在可以理解在设计和代码流方面的差异。令我困扰的是,这两种模式似乎都能解决相同的一组问题,而没有选择其中一个或另一个的真正原因。当我试图自己解决这个问题时,我试图实现一个小例子(从我在"head first:design patterns"一书中找到的例子开始)。在这个例子中,我试图解决同一个问题两次:一次只使用"工厂方法模式",另一次使用"抽象工厂模式"。我会给你看代码,然后我会做一些评论和问题。
公共接口和类1 2 3 4 5 6 | public interface IDough { } public interface ISauce { } public class NYDough : IDough { } public class NYSauce : ISauce { } public class KNDough : IDough { } public class KNSauce : ISauce { } |
纯工厂方法模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | // pure Factory method pattern public abstract class Pizza { protected IDough Dough { get; set; } protected ISauce Sauce { get; set; } protected abstract IDough CreateDough(); protected abstract ISauce CreateSauce(); public void Prepare() { Dough = CreateDough(); Sauce = CreateSauce(); // do stuff with Dough and Sauce } public void Bake() { } public void Cut() { } public void Box() { } } public class NYCheesePizza : Pizza { protected override IDough CreateDough() { return new NYDough(); } protected override ISauce CreateSauce() { return new NYSauce(); } } public class KNCheesePizza : Pizza { protected override IDough CreateDough() { return new KNDough(); } protected override ISauce CreateSauce() { return new KNSauce(); } } public abstract class PizzaStore { public void OrderPizza(string type) { Pizza pizza = CreatePizza(type); pizza.Prepare(); pizza.Bake(); pizza.Cut(); pizza.Box(); } public abstract Pizza CreatePizza(string type); } public class NYPizzaStore : PizzaStore { public override Pizza CreatePizza(string type) { switch (type) { case"cheese": return new NYCheesePizza(); default: return null; } } } public class KNPizzaStore : PizzaStore { public override Pizza CreatePizza(string type) { switch (type) { case"cheese": return new KNCheesePizza(); default: return null; } } } |
号纯抽象工厂模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | public interface IIngredientFactory { IDough createDough(); ISauce createSauce(); } public class NYIngredientFactory : IIngredientFactory { public IDough createDough() { return new NYDough(); } public ISauce createSauce() { return new NYSauce(); } } public class KNIngredientFactory : IIngredientFactory { public IDough createDough() { return new KNDough(); } public ISauce createSauce() { return new KNSauce(); } } public class Pizza { IDough Dough { get; set; } ISauce Sauce { get; set; } IIngredientFactory IngredientFactory { get; set; } public Pizza(IIngredientFactory ingredientFactory) { IngredientFactory = ingredientFactory; } public void Prepare() { Dough = IngredientFactory.createDough(); Sauce = IngredientFactory.createSauce(); } public void Bake() { } public void Cut() { } public void Box() { } } public interface IPizzaFactory { Pizza CreatePizza(string type); } public class NYPizzaFactory : IPizzaFactory { public Pizza CreatePizza(string type) { switch (type) { case"cheese": return new Pizza(new NYIngredientFactory()); default: return null; } } } public class KNPizzaFactory : IPizzaFactory { public Pizza CreatePizza(string type) { switch (type) { case"cheese": return new Pizza(new KNIngredientFactory()); default: return null; } } } public class PizzaStore { IPizzaFactory PizzaFactory { get; set; } public PizzaStore(IPizzaFactory pizzaFactory) { PizzaFactory = pizzaFactory; } public void OrderPizza(string type) { Pizza pizza = PizzaFactory.CreatePizza(type); pizza.Prepare(); pizza.Bake(); pizza.Cut(); pizza.Box(); } } |
如果我使用模式定义,我会为
我的问题是:我首先应该选择"工厂方法模式"的原因是什么?
编辑让我们来看一下第一个实现,即使用工厂方法模式的实现。JessevanAssen建议这是一个模板方法模式,而不是工厂方法模式。我不相信这是对的。我们可以将第一个实现分为两部分:第一部分处理
1)在第一部分中,
Define an interface for creating an object, but let the subclasses decide which class to instantiate. The Factory method lets a class defer instantiation to subclasses.
号
2)在第二部分中,
所以,为了更好地表达(我希望)我没有真正得到的是为什么这样说:
Factory Method pattern is responsible of creating products that belong to one family, while Abstract Factory pattern deals with multiple families of products.
号
正如您从我的示例中看到的(前提是它们是正确的:-)您可以用两种模式来处理相同的内容。
首先,从GoF设计模式书中引用2句话:
"Abstract Factory is often implemented with factory methods."
"Factory Methods are often called by template methods."
号
因此,在工厂方法和抽象工厂之间进行选择不是一个问题,因为后者可以(并且通常是)由前者实现。
抽象工厂的概念(正如amir暗示的那样)是将几个始终在一起的具体类的创建分组。在您的示例中,它们应该是食品成分的NY品种,而不是kn品种。
但是,如果你想允许混合和匹配(用kn面团和ny-souce做的披萨有什么问题?)那么抽象工厂不是你的答案。在这种情况下,每个比萨饼子类都应该决定要创建哪些具体的类。
如果你不想允许这种混合,你应该去抽象工厂。
如果您需要两个相关的工厂方法来做相同的决策,那么最好先在抽象工厂中进行分组。
我要说你的第一个实现不是工厂方法。工厂方法不是抽象的,它们有一些参数,这些参数决定了根据它们实例化什么。