C# p> 此外,请查看此类声明: public class NYPizzaIngredientFactory : IPizzaIngredientFactory<NYPizzaDoughArgs>

C# p> 此外,请查看此类声明: public class NYPizzaIngredientFactory : IPizzaIngredientFactory<NYPizzaDoughArgs>,c#,abstract-factory,C#,Abstract Factory,还有其他方法来表示相同的数据。即使在PizzaDoughOption枚举中有50个值,但这样做可能更容易,建立一个明确、可读的有效选项列表,而不是试图用一堆分支在代码中表示。(如果您想对其进行单元测试,最终还是要在单元测试中对每个组合进行编码。) 有几种方法可以使用这些数据。你可以列出一大堆选择。您可以允许用户从各种选项中进行选择,并在执行时确定它是否匹配有效的组合。或者,他们可以选择任何选项,您可以根据所需选项缩小选项列表。(你想要填馅的面包皮吗?好的,要么是纽约的厚面包皮,要么是芝加哥的厚面

还有其他方法来表示相同的数据。即使在
PizzaDoughOption
枚举中有50个值,但这样做可能更容易,建立一个明确、可读的有效选项列表,而不是试图用一堆分支在代码中表示。(如果您想对其进行单元测试,最终还是要在单元测试中对每个组合进行编码。)

有几种方法可以使用这些数据。你可以列出一大堆选择。您可以允许用户从各种选项中进行选择,并在执行时确定它是否匹配有效的组合。或者,他们可以选择任何选项,您可以根据所需选项缩小选项列表。(你想要填馅的面包皮吗?好的,要么是纽约的厚面包皮,要么是芝加哥的厚面包皮。)

现在,如果您需要工厂根据类型创建面团,您可以执行以下操作:

public interface IDoughFactory
{
    Dough GetDough(PizzaDoughOption doughOption);
}
实现可能看起来像这样。老实说,我可能会在这里使用“工厂”,但现在因为只有三种类型,我会让它更简单

public class DoughFactory : IDoughFactory
{
    // Each of these also implement IDoughFactory
    private readonly NewYorkDoughFactory _newYorkDoughFactory;
    private readonly ChicagoDoughFactory _chicagoDoughFactory;
    private readonly GreekDoughFactory _greekDoughFactory;

    public DoughFactory(
        NewYorkDoughFactory newYorkDoughFactory,
        ChicagoDoughFactory chicagoDoughFactory,
        GreekDoughFactory greekDoughFactory)
    {
        _newYorkDoughFactory = newYorkDoughFactory;
        _chicagoDoughFactory = chicagoDoughFactory;
        _greekDoughFactory = greekDoughFactory;
    }

    public Dough GetDough(PizzaDoughOption doughOption)
    {
        if (MatchesPizzaStyle(doughOption, PizzaStyle.NewYork)) 
            return _newYorkDoughFactory.GetDough(doughOption);
        if (MatchesPizzaStyle(doughOption, PizzaStyle.Chicago)) 
            return _chicagoDoughFactory.GetDough(doughOption);
        if (MatchesPizzaStyle(doughOption, PizzaStyle.Greek)) 
            return _greekDoughFactory.GetDough(doughOption);
        // Throw an exception or return a default dough type. I'd throw the exception.
    }

    private bool MatchesPizzaStyle(PizzaDoughOption doughOption, PizzaStyle pizzaStyle)
    {
        return ((int) doughOptions & (int) pizzaStyle) == (int) pizzaStyle;
    }
}
现在,你们更具体的面团工厂(纽约、芝加哥、希腊)都会收到相同的
比萨饼。如果他们关心选择了“薄”还是“厚”,他们可以处理它。如果这个选项不存在,他们可以忽略它。即使外部类中出现了错误,并且有人以某种方式使用
StuffedCastle
选项调用了
GreekDoughFactory
,它也不会失败。它只是忽略了它

这一切的可能点是什么

首先,制作比萨饼的课程不知道制作正确面团类型的复杂性。它只依赖于面团工厂,传递一个参数,然后得到正确的面团。这很简单,可以测试

其次,您不必在任何地方调用
new
。您可以一直使用依赖项注入。这样,依赖抽象
IDoughFactory
的类就不知道
DoughFactory
有什么依赖项

同样地,也许混凝土面团工厂也有自己的依赖性,并且它们之间存在显著差异。只要这些问题从容器中得到解决并注入到
DoughFactory
中,就可以了,
DoughFactory
就不会知道它们的依赖关系

所有依赖项都连接在DI容器中,但类本身很小、简单且可测试,这取决于抽象,并且不与任何实现耦合


有人可能会看着这个,觉得有点复杂。关键的是,它不仅使单个类保持解耦,而且为将来的更改留下了前进的道路。你的类的设计不应该有太多的改变,不会很好地反映特定类型比萨饼的细节,比萨饼可以也应该改变。你不想因为一种新的比萨饼而不得不重新设计你的比萨饼应用程序。

你不能,类图就是这样设计的(例如,FreshClams在芝加哥不可用)。你不能,类图就是这样设计的(例如,FreshClams在芝加哥不可用)。谢谢,这就是我要找的。谢谢,这就是我要找的。
public class NYPizzaIngredientFactory : IPizzaIngredientFactory<NYPizzaDoughArgs>
public  enum PizzaStyle 
{
    NewYork = 1,
    Chicago = 2,
    Greek = 4
}

public enum CrustType 
{
    Thick = 1024,
    Thin = 2048,
    HandTossed = 4096
}

public enum CrustOption
{
    Stuffed = 32768
}

public enum PizzaDoughOption
{
    NewYorkThin = PizzaStyle.NewYork + CrustType.Thin,
    NewYorkHandTossed = PizzaStyle.NewYork + CrustType.HandTossed,
    NewYorkThick = PizzaStyle.NewYork + CrustType.Thick,
    NewYorkThickStuffed = NewYorkThick + CrustOption.Stuffed,
    ChicagoThin = PizzaStyle.Chicago + CrustType.Thin,
    ChicagoHandTossed = PizzaStyle.Chicago + CrustType.HandTossed,
    ChicagoThick = PizzaStyle.Chicago + CrustType.Thick,
    ChicagoThickStuffed = ChicagoThick + CrustOption.Stuffed,
    Greek = PizzaStyle.Greek // only comes one way?
}
public interface IDoughFactory
{
    Dough GetDough(PizzaDoughOption doughOption);
}
public class DoughFactory : IDoughFactory
{
    // Each of these also implement IDoughFactory
    private readonly NewYorkDoughFactory _newYorkDoughFactory;
    private readonly ChicagoDoughFactory _chicagoDoughFactory;
    private readonly GreekDoughFactory _greekDoughFactory;

    public DoughFactory(
        NewYorkDoughFactory newYorkDoughFactory,
        ChicagoDoughFactory chicagoDoughFactory,
        GreekDoughFactory greekDoughFactory)
    {
        _newYorkDoughFactory = newYorkDoughFactory;
        _chicagoDoughFactory = chicagoDoughFactory;
        _greekDoughFactory = greekDoughFactory;
    }

    public Dough GetDough(PizzaDoughOption doughOption)
    {
        if (MatchesPizzaStyle(doughOption, PizzaStyle.NewYork)) 
            return _newYorkDoughFactory.GetDough(doughOption);
        if (MatchesPizzaStyle(doughOption, PizzaStyle.Chicago)) 
            return _chicagoDoughFactory.GetDough(doughOption);
        if (MatchesPizzaStyle(doughOption, PizzaStyle.Greek)) 
            return _greekDoughFactory.GetDough(doughOption);
        // Throw an exception or return a default dough type. I'd throw the exception.
    }

    private bool MatchesPizzaStyle(PizzaDoughOption doughOption, PizzaStyle pizzaStyle)
    {
        return ((int) doughOptions & (int) pizzaStyle) == (int) pizzaStyle;
    }
}