简体   繁体   English

C#中的工厂模式实现

[英]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. 这里, Feed是一个抽象类,不同的类从中继承。 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 . 工厂总是会有一些构造函数逻辑,至少有一个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. 现在我假设你的Feed类有一个没有参数的默认构造函数。 In that case, you can implement a factory method directly from the abstract class Feed. 在这种情况下,您可以直接从抽象类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: 现在,如果你想获得继承自Feed的给定类型的单例(让我们称之为SpecializedFeedType ),你所要做的就是:

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. Edit2:更改了一些语法错误。

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. 当您调用RegisterFeed方法时,您需要传递Feed类的具体实例。 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. 只需注册要创建的类的类型,然后使用Activator.CreateInstance创建该类型的实例。

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

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. 请注意所有Feeds必须实现IFeedFactory接口并实现必要的方法。

//From the client //来自客户端

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM