C#中的工厂模式实现

时间:2010-12-21 10:07:43

标签: c# design-patterns repository factory

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

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];
    }
}

这里,Feed是一个抽象类,不同的类从中继承。如何注册不同的课程?是否可以从构造函数中完成它?

5 个答案:

答案 0 :(得分:7)

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

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

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

之后,您不需要注册方法。 检索单身人士时,应自动填写字典。

现在我假设你的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;
    }
}

现在回到你的单身人士资料库。

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)];
        }
    }
}

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

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

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

SpecializedFeedType singleton = FeedSingletonRepository.GetFeed();

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

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

答案 1 :(得分:6)

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

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

答案 2 :(得分:1)

调用RegisterFeed方法时,需要传递Feed类的具体实例。因此调用者有责任提供具体的实现。

答案 3 :(得分:1)

只需注册要创建的类的类型,然后使用Activator.CreateInstance创建该类型的实例。

它应该以这种方式工作:

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;
}

您可以按以下方式致电RegisterFeed

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

答案 4 :(得分:0)

class FeedFactory {


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

    }

}

注意所有Feeds必须实现IFeedFactory接口并实现必要的方法。

//来自客户端

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