Reputation: 5236
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
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
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
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
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
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