C#中的工厂模式实现

Aks*_*Aks 4 c# design-patterns factory repository

我正在实现一个看起来如下的工厂模式.

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];
    }
}
Run Code Online (Sandbox Code Playgroud)

Feed是一个抽象类,不同的类从中继承.如何注册不同的课程?是否有可能从他们的构造函数中做到这一点?

Evr*_*glu 7

这不是工厂模式.工厂总是会有一些构造函数逻辑,至少有一个new.这就是工厂的想法:调用者不必担心如何创建对象.这是一个单例存储库.

首先,您应该使用类型索引字典,而不是使用数组.

private static Dictionary<Type, Feed> _singletons = new Dictionary<Type, Feed>();
Run Code Online (Sandbox Code Playgroud)

之后,您不需要注册方法.检索单例时,应自动填充字典.

现在我假设你的Feed类有一个没有参数的默认构造函数.在这种情况下,您可以直接从抽象类Feed实现工厂方法.我们将在这里使用一些泛型,因为它允许您控制继承:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在回到你的单例存储库.

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)];
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,我包含了一个线程安全行为,当您使用单例时,这是一件好事.

现在,如果你想获得继承的给定类型的单例Feed(让我们调用它SpecializedFeedType),你所要做的就是:

var singleton = FeedSingletonRepository.GetFeed<SpecializedFeedType>();
Run Code Online (Sandbox Code Playgroud)

要么

SpecializedFeedType singleton = FeedSingletonRepository.GetFeed();
Run Code Online (Sandbox Code Playgroud)

这是同一行,语法略有不同.

Edit2:更改了一些语法错误.


Tim*_*ass 6

正如旁注 - 作为工厂旨在包装创作,您正在创建对象并将其注册到工厂是一个奇怪的选择.这是一个对象存储库而不是工厂,还是比我看到的更多的类?

如果它是一个对象存储库,那么您可能还会在其他问题中找到一些额外的灵感,比如这个问题.