【发布时间】:2012-02-15 16:36:25
【问题描述】:
我知道以前有人问过类似的问题。在过去的几天里,我已经阅读了很多关于此的内容,我想我现在可以理解设计和代码流方面的差异。困扰我的是,这两种模式似乎都可以解决相同的一组问题,而没有真正的理由来选择一个或另一个。 当我试图自己解决这个问题时,我尝试实现一个小例子(从我在“Head First:Design patterns”一书中找到的那个开始)。 在此示例中,我尝试两次解决相同的问题:一次仅使用“工厂方法模式”,另一次使用“抽象工厂模式”。我将向您展示代码,然后我将制作一些 cmets 和问题。
常用接口和类
public interface IDough { }
public interface ISauce { }
public class NYDough : IDough { }
public class NYSauce : ISauce { }
public class KNDough : IDough { }
public class KNSauce : ISauce { }
纯工厂方法模式
// 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;
}
}
}
纯抽象工厂模式
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();
}
}
如果我使用了模式定义,我会为PizzaStore 选择“工厂方法模式”(因为它只构建一种类型的对象,Pizza),为IngredientFactory 选择“抽象工厂模式”。无论如何,另一个设计原则指出你应该“更喜欢组合而不是继承”,这表明我应该始终使用“抽象工厂模式”。
我的问题是:首先我应该选择“工厂方法模式”的原因是什么?
编辑
让我们看一下第一个实现,它使用工厂方法模式。 Jesse van Assen 建议这是模板方法模式而不是工厂方法模式。我不相信这是正确的。
我们可以将第一个实现分为两部分:第一个处理Pizza,第二个处理PizzaStore。
1) 在第一部分中,Pizza 是依赖于某种具体的 Dough and Sauce 的客户端。为了将 Pizza 与我使用的具体对象分离,在 Pizza 类中,仅引用接口(@987654331@ 和 ISauce),我让 Pizza 的子类决定哪个具体的 Dough 和 @987654335 @ 选择。对我来说,这完全符合工厂方法模式的定义:
定义一个用于创建对象的接口,但让子类决定实例化哪个类。 Factory 方法允许类将实例化推迟到子类。
2) 第二部分中的PizzaStore 是客户端,它依赖于具体的Pizza。我应用了上面讨论的相同原则。
所以,为了更好地表达(我希望)我没有真正理解的是为什么这么说:
工厂方法模式负责创建属于一个系列的产品,而抽象工厂模式处理多个产品系列。
正如您从我的示例中看到的(只要它们是正确的 :-))您可以使用两种模式来实现相同的东西。
【问题讨论】:
标签: c# design-patterns factory-pattern