Singleton-Factory的替代品

时间:2012-03-16 03:36:04

标签: c# singleton factory single-instance

我正在编写一个我无法控制的类库的包装器。在这个库中是一个类(让我们称之为Target)我想要确保它只被实例化一次,但它本身不是一个单例。我想过像这样使用Singleton-Factory模式:

internal sealed class SingletonFactory
{
    private static readonly SingletonFactory manager = new SingletonFactory();

    private readonly Target target;

    private static SingletonFactory() { }

    private SingletonFactory()
    {
        target = new Target();
        target.Init("foo");
    }

    internal static SingletonFactory Instance
    {
        get { return manager; }
    }

    internal Target Target
    {
        get { return target; }
    }
}

我可以这样做:

var targetInstance = SingletonFactory.Instance.Target;

然后我想通过使Factory完全静态来简化这个:

internal static class StaticFactory
{
    private static readonly Target target;

    private static StaticFactory()
    {
        target = new Target();
        target.Init("foo");
    }

    internal static Target Target 
    {
        get { return target; }
    }
}

对目标实例的访问变为:

var targetInstance StaticFactory.Target;

我非常确定这个StaticFactory是线程安全的,并提供对目标类的单个实例的全局访问。我有没有想过这有什么不对吗?

2 个答案:

答案 0 :(得分:1)

同样的事情,除了你的静态构造函数上有private关键字,这是不允许的。

internal static class StaticFactory
{
    public static Target Target = new Target();

    static StaticFactory()
    {
       Target.Init("foo");
    }
}

你可以得到幻想,把它全部塞进懒惰:

public static Lazy<Target> Target =
      new Lazy<Target>(() => { var t = new Target(); t.Init(""); return t; });

您还可以建立一个Facade,它将为您提供与Target相同的语义,但将其保留为单个实例。它还为您提供了初始化Target对象的位置和时间的空间。

public class TargetFacade
{
   private static Target _target = new Target();

   static StaticFactory()
   {
      _target.Init("foo");
   }

   //Wrap Target's methods here.
   public int Score { get { return _target.Score } }; 
}

答案 1 :(得分:1)

我不确定你的构造函数是否真的是线程安全的,因为它在技术上可以同时从不同的线程访问。您可以锁定private static readonly object Lock = new object();以强制执行线程安全。

如果我们谈论的是C#4,您可能还想看Lazy<T>这里http://msdn.microsoft.com/de-de/library/ee792409.aspx。它支持线程安全的创建模式LazyThreadSafetyMode,允许您在安全性和性能之间进行权衡。

旁注: 最后,不使用静态可能是一个更好的设计决策,因为您可以防止体系结构上不可见的依赖关系并获得交换实现的能力。使用抽象工厂可以解决这个问题(并且还可以提供良好的单元测试体验)。