I'm implementing a factory pattern that looks as follow开发者_运维百科s.
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?
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.
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.
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.
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));
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();
精彩评论