【问题标题】:Factory Pattern implementation in C#C# 中的工厂模式实现
【发布时间】:2010-12-21 10:07:42
【问题描述】:

我正在实现如下所示的工厂模式。

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 是一个抽象类,不同的类都继承自该类。如何注册不同的课程?是否可以从他们的构造函数中做到这一点?

【问题讨论】:

标签: c# design-patterns repository factory


【解决方案1】:

这不是工厂模式。工厂中总会有一些构造函数逻辑,至少有一个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:更改了一些语法错误。

【讨论】:

  • 当你打电话给typeof(T).GetInstance()时,GetInstance() 电话不应该来自班级而不是System.Type吗?
  • 是的,您正在按类型索引一个实例数组。这样你就得到了一个关系类型 => 实例,如果该实例是给定类型的单例。
  • 是的,但typeof(T) 是一种类型,而不是提要类的实例。所以typeof(T).GetInstance() 没有意义
  • 好吧,实际上你是对的!我现在正在调查。
  • 可以写T.GetInstance(),该方法是静态的,但它不起作用。我正在努力寻找一种方法来做到这一点!
【解决方案2】:

顺便说一句——由于工厂旨在包装创建,因此创建对象并将其注册到工厂是一个奇怪的选择。这是一个对象存储库而不是工厂,还是这个类比我看到的更多?

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

【讨论】:

  • 通常工厂会创建对象——一个简单的实现会有一个带有 Create 方法的工厂接口,以及可以创建特定类型的工厂类的具体实现。有一些变化,但关键是它可以为您处理创建。如果你想重用它们,它也可以做你正在做的事情并缓存对象实例,但是你可能明确地想要拆分工厂和缓存/存储库方面。这取决于您想要实现的目标:) 如果您此时正在探索,我会首先得到满足您目标的东西。
【解决方案3】:

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

【讨论】:

  • 那么调用者是提要类型之一吗?
  • 调用者可以是任何东西。当它调用 RegisterFeed 方法时,它需要传递 Feed 的特定实现。
  • 假设我有一个class FeedTypeA : Feed。如果我在FeedTypeA 内声明FeedTypeA 的公共静态对象并将寄存器放入构造函数中。这行得通吗?
  • 是的,它会起作用,您可以将this 传递给RegisterFeed 方法。
【解决方案4】:

只需注册您要创建的类的类型,然后使用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));

【讨论】:

    【解决方案5】:
    class FeedFactory {
    
    
        public IFeedFactory GetFeedFactory(string type) {
           switch(type) {
              case "1": return new Feed1(); break;
              case "2": return new Feed2(); break;
           }
    
        }
    
    }
    

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

    //来自客户端

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多