Aks
Aks

Reputation: 5236

Factory Pattern implementation in C#

I'm implementing a factory pattern that looks as follows.

public class FeedFactory
{
    #region Singleton Pattern
    //..
    #endregion

    private static Feed[] _factory = new Feed[(int)FeedType.Total];

    public void RegisterFeed(FeedType feedType,Feed feed)
    {
        if (_factory[(int)feedType] == null)
        {
            _factory[(int)feedType] = feed;
        }
        else
        {
            // already registered
        }
    }

    public Feed GetFeed(FeedType feedType)
    {
        return _factory[(int)feedType];
    }
}

Here, Feed is an abstract class from which the different classes inherit. How can I register the different classes? Is it possible to do it from their constructor?

Upvotes: 5

Views: 6718

Answers (5)

Evren Kuzucuoglu
Evren Kuzucuoglu

Reputation: 3885

This is not a factory pattern. A factory will always have some constructor logic in it, at least one new. That's the idea of a factory: the caller doesn't have to worry about how objects are created. This is a singleton repository.

So first of all, instead of using an array, you should be having a type indexed dictionary.

private static Dictionary<Type, Feed> _singletons = new Dictionary<Type, Feed>();

After that, you don't need a register method. The dictionary should be filled automatically when you retrieve singletons.

Now I suppose your Feed class has a default constructor without arguments. In that case, you can implement a factory method directly from the abstract class Feed. We're going to use some generics here, because it allows you to control inheritance:

public abstract class Feed
{
    public static T GetInstance<T>() where T:Feed, new()
    {
        T instance = new T();
        // TODO: Implement here other initializing behaviour
        return instance;
    }
}

Now back to your singleton repository.

public class FeedSingletonRepository
{
    private static readonly object _padlock = new object();
    private static Dictionary<Type, Feed> _singletons = new Dictionary<Type, Feed>();

    public static T GetFeed<T>() where T:Feed
    {
        lock(_padlock)
        {
             if (!_singletons.ContainsKey(typeof(T))
             {
                 _singletons[typeof(T)] = Feed.GetInstance<T>();
             }
             return (T)_singletons[typeof(T)];
        }
    }
}

Note that I included a threadsafe behaviour which is a good thing to do when you work with singletons.

Now if you want to get the singleton for a given type inheriting from Feed (let's call it SpecializedFeedType), all you have to do is:

var singleton = FeedSingletonRepository.GetFeed<SpecializedFeedType>();

or

SpecializedFeedType singleton = FeedSingletonRepository.GetFeed();

which is the same line with a slightly different syntax.

Edit2: changed some syntax errors.

Upvotes: 8

codymanix
codymanix

Reputation: 29520

Just register the type of the classes you want to create, then use Activator.CreateInstance to create instances of that type.

It should work this way:

private static Type[] _factory = new Type[(int)FeedType.Total];

public void RegisterFeed(FeedType feedType, Type type)
{
  ...
  _factory[(int)feedType] = type;
  ...
}

public Feed GetFeed(FeedType feedType)
{
    return Activator.CreateInstance(_factory[(int)feedType]) as Feed;
}

You can call RegisterFeed like the following:

RegisterFeed(FeedType.SomethingSpecial, typeof(MyDerivedSpecialFeed));

Upvotes: 1

Orson
Orson

Reputation: 15451

class FeedFactory {


    public IFeedFactory GetFeedFactory(string type) {
       switch(type) {
          case "1": return new Feed1(); break;
          case "2": return new Feed2(); break;
       }

    }

}

Note all Feeds Must implement an IFeedFactory interface and implement the method necessary.

//From the client

FeedFactory ff1 = new FeedFactory();
IFeedFactory obj = ff1.GetFeedFactory("1");
obj.ExecuteMethod();

Upvotes: 0

Tim Barrass
Tim Barrass

Reputation: 4939

Just as a side note -- as a factory is intended to wrap creation, it's a curious choice that you're creating objects and registering them with the factory. Is this more an object repository than a factory, or is there more to the class than I'm seeing?

If it is an object repository, then you might also find some extra inspiration in other questions, like this one.

Upvotes: 6

Darin Dimitrov
Darin Dimitrov

Reputation: 1039398

When you call the RegisterFeed method you need to pass a concrete instance of a Feed class. So it is the responsibility of the caller to provide the concrete implementation.

Upvotes: 1

Related Questions