Mil*_*oin 7 c# design-patterns factory
我有一个(不断增长的)数据生成器列表.我需要的生成器是由工厂类创建的.生成器都实现了一个通用接口,其中包括一个静态字符串name.
我想做什么:使用上述名称的字符串参数调用factory.Create方法.create方法使用此名称查找生成器并返回所述生成器的新实例.
我认为这样做的好处是:我只需添加新的生成器类而无需编辑工厂.
题:
最后我会这样称呼工厂(简化):
//Caller
public DataModel GetData2()
{
var generator = new DataFactory().Create("Gen.2");
return generator.GetData();
}
//Factory
public class DataFactory
{
public AbstractDataGenerator Create(string type)
{
//Here the magic happens to find all implementations of IDataGenerator
var allGenerators = GetImplementations();
var generator = allGenerators.FirstOrDefault(f => f.name == type);
if (generator != null)
return (AbstractDataGenerator)Activator.CreateInstance(generator);
else
return null;
}
}
//Interface
public abstract class AbstractDataGenerator
{
public static string name;
public abstract DataModel GetData();
}
//Data-Generators
public class DataGen1 : AbstractDataGenerator
{
public static string name = "Gen.1";
public DataModel GetData()
{
return new DataModel("1");
}
}
public class DataGen2 : AbstractDataGenerator
{
public static string name = "Gen.2";
public DataModel GetData()
{
return new DataModel("2");
}
}
Run Code Online (Sandbox Code Playgroud)
GetImplementations()工厂的魔力应该通过反射还是以某种方式完成?我应该采用完全不同的方法吗?
由于答案参考IoC和DI:该项目已经使用了NInject,因此可以使用.从接口切换到抽象类.
这是处理这个问题的好方法吗?
拥有一个工厂来通过某个键获取您需要的逻辑类的实例 - 我相信这是一个好方法。这是我自己经常使用的模式。关于您拥有密钥的方式 - 我宁愿不将其作为static成员(不管接口不能有静态成员这一事实),而只是将其作为 aproperty并将基类添加到IDataGenerator. 该基类将有一个构造函数,该构造函数将获取name- 这样,DataGenerator您创建的每个新类都必须设置它,并且您不会忘记。
关于将其name作为string- 我个人更喜欢将其“强类型化”。我的意思是,如果我传递Gen . 2而不是Gen.2字符串,我只会在运行时发现这个问题。可能的其他方式(如果你愿意,因为简单的字符串也可以 - 口味问题):
enumRequestGenerator对象,每个Generator存在IDataGenerator<TGeneratorRequest>。这可能有点矫枉过正,但如果您还需要额外的信息来创建DataGenerator它们之间不同的文件,那么请考虑它。如何找到所有发电机?反思接口的每个实现/命名空间的每个成员(对于生成器及其接口来说是唯一的)?
是的,反思可能是一个好方法。然而,我建议阅读Dependency Injection并IoC Containers喜欢Castle Windsor例如。有些东西已经为你实现了,所以为什么要重新发明轮子:)
DI在我看来,这是一个改变生活的概念
将这种工作方式称为工厂是否正确,或者这是某种不同的模式?
是啊。这是一家工厂
工厂中神奇的 GetImplementations() 应该通过反射完成还是以某种方式不同?
参见问题2的答案