mardi 5 juillet 2016

Factory Pattern, selecting by Property

I have a (growing) list of Data-Generators. The generator that I need is created by a factory class. The generators all implement a common Interface, which includes among other things a static string name.

What I would like to do: Call the factory.Create method with a string parameter for the above mentioned name. The create method finds the generator with this name and returns a new instance of said generator.

Bonus in my opinion of this way to do it: I only have to add new generator classes without having to edit the factory.

Question:

  1. Is this a good way to handle this problem?
  2. How can I find all generators? Reflection over every implementation of the interface/every member of the namespace (unique for the generators + their interface)?
  3. Is it correct to call this way of working a factory, or is this some different pattern?

In the end I would call the factory like this (simplified):

//Caller
public DataModel GetData2()
{
    var generator = new DataFactory().Create("Gen.2");
    return generator.GetData();
}

//Factory
public class DataFactory
{
    public IDataGenerator 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 (IDataGenerator)Activator.CreateInstance(generator);
        else
            return null;
    }
}

//Interface
public interface IDataGenerator
{
    static string name;
    DataModel GetData();
}

//Data-Generators
public class DataGen1 : IDataGenerator
{
    public static string name = "Gen.1";
    public DataModel GetData()
    {
        return new DataModel("1");
    }
}
public class DataGen2 : IDataGenerator
{
    public static string name = "Gen.2";
    public DataModel GetData()
    {
        return new DataModel("2");
    }
}

Should the magic GetImplementations() in the factory be done via Reflection or somehow different? Should I use a completely different approach?

Aucun commentaire:

Enregistrer un commentaire