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;
}
}