工厂模式,按财产选择

Mil*_*oin 7 c# design-patterns factory

我有一个(不断增长的)数据生成器列表.我需要的生成器是由工厂类创建的.生成器都实现了一个通用接口,其中包括一个静态字符串name.

我想做什么:使用上述名称的字符串参数调用factory.Create方法.create方法使用此名称查找生成器并返回所述生成器的新实例.

我认为这样做的好处是:我只需添加新的生成器类而无需编辑工厂.

题:

  1. 这是处理这个问题的好方法吗?
  2. 我怎样才能找到所有发电机?反映接口的每个实现/命名空间的每个成员(对于生成器及其接口是唯一的)?
  3. 称这种工厂工作方式是正确的,还是这种模式不同?

最后我会这样称呼工厂(简化):

//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,因此可以使用.从接口切换到抽象类.

Gil*_*een 4

这是处理这个问题的好方法吗?

拥有一个工厂来通过某个键获取您需要的逻辑类的实例 - 我相信这是一个好方法。这是我自己经常使用的模式。关于您拥有密钥的方式 - 我宁愿不将其作为static成员(不管接口不能有静态成员这一事实),而只是将其作为 aproperty并将基类添加到IDataGenerator. 该基类将有一个构造函数,该构造函数将获取name- 这样,DataGenerator您创建的每个新类都必须设置它,并且您不会忘记。


关于将其name作为string- 我个人更喜欢将其“强类型化”。我的意思是,如果我传递Gen . 2而不是Gen.2字符串,我只会在运行时发现这个问题。可能的其他方式(如果你愿意,因为简单的字符串也可以 - 口味问题):

  • 将字符串替换为enum
  • 有一个静态类,其中包含所有值的静态只读字符串 - 然后在代码中使用这些值。您可以获得智能感知的好处,并且不会弄错字符串,但比枚举更好 - 您仍然可以传递不在“列表”中的字符串,以便您可以添加新字符串作为附加组件。
  • 拥有一个RequestGenerator对象,每个Generator存在IDataGenerator<TGeneratorRequest>。这可能有点矫枉过正,但如果您还需要额外的信息来创建DataGenerator它们之间不同的文件,那么请考虑它。

如何找到所有发电机?反思接口的每个实现/命名空间的每个成员(对于生成器及其接口来说是唯一的)?

是的,反思可能是一个好方法。然而,我建议阅读Dependency InjectionIoC Containers喜欢Castle Windsor例如。有些东西已经为你实现了,所以为什么要重新发明轮子:)

DI在我看来,这是一个改变生活的概念

将这种工作方式称为工厂是否正确,或者这是某种不同的模式?

是啊。这是一家工厂

工厂中神奇的 GetImplementations() 应该通过反射完成还是以某种方式不同?

参见问题2的答案